Debugging IRL Problems With Heuristics

Tyler
Creative Labs
Published in
10 min readDec 6, 2019

Introduction

Programming is a skill that has developed itself to be ubiquitous within our society. It’s a bit of a cliche to suggest the idea of making programming a mandatory course in standardized education, not so much for the process itself, but rather the skills that come with it. The subject is rarely correlated to abstract benefits — while individuals are quick to bring up the tangible benefits that arise from programming, such as employment opportunities and promotions, the subject of applying programmatic disciplines into our daily lives remains a weird and quirky subject. I thought it would be interesting to write about the cross overs between programmatic thinking and fixing real-life problems, as people rarely associate writing code with that of day to day issues.

This article centers mostly around the use of heuristics (ways of solving a problem) used in mathematics and computer science, more specifically the act of applying heuristic techniques to my real-life problems. While I find the actual application of it to be a bit of a stretch and up to debate, I wish to show the general chain of axiomatic thinking used in programming to motivate the prospect of teaching programming to students at an early age.

General Heuristic

The original copy for “How to Solve It”

The general heuristic I use when programming could be modeled after Pólya’s “How to Solve It” book on solving mathematical problems. Written in 1945, the book primarily centers around Pólya’s heuristic problem-solving techniques for math problems, which I frequently use when developing software or code, as the process is arguably more or less the same.

These general statements aren’t exclusive to mathematics, as I hope to demonstrate in this article.

“How to Solve It” primarily centers around four major principles for heuristic thinking, while deceptively simple, are:

1) Understand the problem.

2) Make a plan.

3) Carry out the plan.

4) Look back on your work. How could it be better?

For the sake of brevity, each principle will be expanded on in its corresponding sub-section, which will be related to the problem scenario I will briefly layout.

Problem Scenario

The problem I’ll primarily be solving in this article is “struggling with school”, as it’s a situation I’ve struggled with and was able to dramatically improve by following these guidelines. It’s still an ongoing process, and still being improved upon.

Step 1: Identifying the Problem

I would wager that most people undervalue the step of “identifying the problem” when trying to fix an issue, as it seems to be the most intuitive out of all the steps required. It’s difficult to convince people to even consider applying these heuristics after introducing this preliminary principle: if someone says “I have a problem”, it’s somewhat difficult to tell them to even consider the statement, “do you actually understand the problem?” as it’s instinctual to just stop and ask for help once one hits this point.

In heuristic problem solving, deriving a testable solution is built off one’s understanding of the problem statement. Neglecting to properly define the problem can build a weak if not absent foundation for future steps. Image Source: Neal R Pellis

One of the main advantages of this preliminary step is to maximize the variables one can work and leverage with, which will be used in later steps of the heuristic process. For example, let’s identify the known variables from the initial statement, “I am struggling with school”.

“I am struggling with school”

  • I am a student.
  • I find school to be a struggle.

Using this as a basis, it’s not obvious what variables are at play, and we’re not any closer to fixing the issue — this statement revealed to us very little information in regards to finding a solution. In other words, there’s very little to expand or build off with this basic statement. Suppose one were to instead say, “I am having difficulties understanding the material in my classes”, we could extend the list of known variables to:

“I am having difficulties understanding the material in my classes”

  • I am a student.
  • I am taking multiple classes
  • I am having issues understanding what is taught in those mentioned classes.

While it feels like we’ve made very little progress, we at least know that the concepts taught in classes aren’t being understood, which is just a continuation of “struggling with school”. This has the potential of allowing us to investigate the contributing factors causing “having issues understanding what is taught”, which may help us find a solution to my more general problem.

Without listing every sub-variation of the problem I went through, I found a general problem statement that gave me the most variables to work with, while maintaining the essence of the original problem.

“I am having issues both with understanding the material taught and finishing my homework, and I constantly find myself falling behind in my coursework.”

Which can see is an extended analog of:

“I am struggling with school.”

It seems rather trivial to do an activity like this, but extending our understanding of the problem allows to list the following observations, without bias (hopefully):

“I am having issues both with understanding the material taught and finishing my homework, and I constantly find myself falling behind in my coursework.”

  • I don’t understand what is being taught.
  • There may be some connection between falling behind in my coursework and understanding the material.
  • There may be some link between falling behind in my course work and finishing my homework.
  • A lot of the activities in my life that have a deadline, and those activities are being done at the very last second.

These were the issues I feel that most contributed to the overlying issue of “I am struggling with school.”

Step 2: Making a Plan

After identifying the problem, choosing a plan to fix the situation can seem like the most foreign step for most — it may seem strange to choose a plan-devising technique to help derive a solution to a problem, as formal planning is something rarely taught in school.

Pólya gave a list of heuristics (steps to try to solve a problem) he recommended trying, such as “solve a simpler problem” or “solve a variation of the problem”. I chose to try “solve a variation of the problem”:

(From Wikipedia) “solve a variation of the problem”:

Can you vary or change your problem to create a new problem (or set of problems) whose solution(s) will help you solve your original problem?

When making a variation of the problem, I typically make it my goal to create a problem with a testable hypothesis and a measurable conclusion. Using our extended understanding of the problem statement, it’s possible to create a hypothesis in the form of “if x then y” , where x is some obtainable goal, and y will (hopefully) happen if x is met. In other words, I try and create a logical chain of reasoning, where if I take the steps to satisfy x, y should happen also. My hypothesis then became:

“If I’m not making everything I do last minute, then it would be easier to find time to study and finish my homework.”

I used this as a basis to devise a solution: while these steps seem obvious, being able to quantify a concrete goal makes it easier to take the steps needed to achieve the desired result. Rather than trying to solve the issue of “struggling with school”, it’s now my goal to “not making everything I do last minute”, which is much easier to develop a testable plan of attack for.

Now, finding a way to “not fall behind on coursework” is my primary goal (if x), and seeing how close this will bring me towards “finding time to study and finish my homework” (then y) .

I generally refer to the Wikipedia entry for “How To Solve It” for the list of heuristics to experiment with and see which informal description feels the most appropriate for the problem at hand. Source: https://en.wikipedia.org/wiki/How_to_Solve_It

In the process of solving the variation of the problem of, “not making everything I do last minute”, I came up with a list of sub-goals that I felt would help me achieve this variation of the problem:

1) Setting calendar dates for important events.

2) Allocating work sessions ahead of time to ensure I had the time to finish my studying goals and homework.

3) Making the time I spent studying more efficient.

Attacking these 3 sub-problems of the plan individually were definitive, concrete goals towards fixing the initial problem of “struggling with school”: the lack of ambiguity gave measurable milestones I could work towards, and if I met my personal guidelines, would provide better results if my hypothesis were true.

Step 3) Carrying out the Plan

This part is generally the least abstract part of this problem-solving technique as it usually entails just trying what we hypothesized, and measuring the outcomes. Although it’s been mostly theory up until this point, this is the step that requires the self-discipline to maintain the set-out goal in order to test if our hypothesis is true.

Although this step is fairly concrete on paper, there’s a lot of passive tasks one needs to take to make this step worthwhile. For example, although I created a list of steps I was going to take to carry out the plan, I had to accept the steps were imperfect and still needed revisions. As a result, after each week, I sat down and reflected on the productivity of each step.

In my case, I had to reflect on how the steps I took for “not making everything I do last-minute” reflected my end goal of “easier to find time to study and finish my homework”, and trying deciding if the steps I took were providing meaningful results.

In my case, the sub-goal of “allocating work sessions ahead of time to ensure I had the time to finish my studying goals and homework” was not effective, as I found myself not having enough time to do my coursework in their designated time blocks, which did not help with my overarching goal “not making everything I do last minute”. This is part of the test-feedback process of carrying out the plan one needs to passively monitor — try what we set out to do, and see if the results we measure reflect on our desired goal.

Step 4: Revising the Plan

As stated in the previous section, I initially allocated time slots for certain subjects and tried to complete those steps within the designated time frame. This however neglected to account for the fact if one class took longer than another, I would be placed in another, worse situation. In other words, this step towards the goal of “not making everything I do last-minute” was not helping.

Just as I derived potential solutions to the initial problem of “struggling with school,’’ sitting down and revising this sub-issue became a recursive process I had to undergo. To briefly illustrate this sub-problem, I redid a shorter version of the heuristic:

Identifying the Issue:

“Setting time slots to study in is not working” (initial problem)

“I am unable to complete my course work by studying in time slots” (variation of the initial problem)

“Sometimes time slots take longer than expected, sometimes time slots take shorter than expected” (more variations)

….

Making a Plan:

(the same thing as the previous section, wherein I investigated various heuristics and saw what resonated with me the most )

And I found my solution to be “dynamically setting my study times depending on how difficult/easy the assignment was upon initial review.” Rather than setting the time blindly, as I had done before, I would look at the assignment holistically, and make a best-guess approximation of how long it would take me to finish, then allocate time within the week to complete it.

This proved more fruitful in returns than simply allocating time slots for studying, as I found that I needed to better manage some classes more than others, depending on upcoming midterms and homework.

The “revising the plan” section remains an ongoing process from start to finish — being able to identify the effectiveness of various sub-goals and plans and how close they bring us towards the end goal is a dynamic process, and recursively applying these heuristics to problems as they appear is key towards working towards a solution.

Results

After being on this process for weeks 4 now, I have to say there’s a strong degree of pseudo-intellectualism ingrained within it. Life generally is more complex and can’t be entirely modeled by black and white “if x then y” statements, rather, it’s filled with ambiguity and ill-defined definitions. The use of heuristics, however, I feel is still justified. It’s a bit of a cliche to quote Einstein, but here’s a quote about Einstein quoting heuristics.

“…Einstein used the term “heuristic” to indicate that he considered the view he presented therein as incomplete, false even, but still useful… As used by Einstein, then, a heuristic is an approach to a problem that is necessarily incomplete given the knowledge available, and hence unavoidably false, but which is useful nonetheless for guiding thinking in appropriate directions” — Gerd and Peter Express (1999 p 25–26)

While heuristics are generally incomplete given the limited knowledge we have over a situation, heuristics are a great stepping stone for finding out what’s true by discovering what assumptions we have are untrue, thus giving one a cardinal direction to move towards in regards to finding a solution. Rather than aimlessly wandering a dark room for a solution, heuristics provide some sense of direction that is bound to make some progress, regardless if the hypothesis is a failure.

Heuristics excel when we’re able to quantify parts our life into discrete variables, and being able to test if each variable is behaving the way it is expected follows from that of a programming based discipline. While the process of assigning variables, testing hypothesis, and measuring results is innate to other fields of science and thinking, I can’t think of a stronger discipline than that of programmatic thinking to train one’s mind to think in terms of concrete variables rather than arbitrary assumptions.

Developing a program requires being able to identify the cogs in a complex machine, that when ran together, can create powerful results. It’s a discipline on its own to sit down and identify what discrete variables are needed in order to solve a problem, and seeing which cogs need to be removed / re-adjusted in order to get the machine running smoothly

As such, when I recommend people learning to program at an early age, the discipline of being to put real-life problems into discrete variables is the take away I hope people also value when pursuing a programmatic discipline: that not all the benefits are purely marketable, but rather, training one’s mental capacity to see the world through measurable variables and theories.

--

--