[{"content":"Overview Problem Statement Prove that the following problem is NP-complete: given an undirected graph G=(V,E)G = (V, E) and an integer kk, return a clique of size kk as well as an independent set of size kk, provided both exist. Approach We call the problem CIS for brevity. First, we show that the problem is in the NP computational class. Next, we show we can reduce the known NP-complete problem Clique →\\rightarrow CIS. Finally, we provide a bidirectional proof to prove that the reduction is correct, which also proves that CIS∈NPCIS\\in NP-complete. CIS in NP We need to show that for any solution SS for and instance II of CIS can be verified in polynomial time. To validate the SS clique, we first check that there are not more than kk vertices in SS. This takes O(n)O(n) time. Next, we check that all pairs are strongly connected (to satisfy the definition of a clique). We do this by looking at each x,yx,y vertex and ensuring there is an edge between them. This takes O(n2)O(n^2) time. The above is poly-time to the input, thus we can assert CIS∈NPCIS\\in NP. CIS in NP-complete Clique -\u003e CIS We now reduce a known NP-complete problem, Clique, to CIS. We must take care of the wording of the problem: it will only return IFF there is both a clique and an independent set of size kk. Clique takes a graph, G=(V,E)G=(V,E) and a goal gg. We can take the GG and modify it. We add vertices to the graph which are not connected to any edges, such that there are gg new vertices, for a total of: ∥V′∥=∥V∥+g\\|V'\\|=\\|V\\|+g. Now we pass G′G' (the transformed graph) and gg to CIS. If there is a clique of size gg, CIS will return that clique as well as an independent set of size gg (which we guaranteed by the above). Our illustration captures what’s going on. The transformation is poly-time, taking at most O(n+m) to add vertices to the graph. {: height=“550” } Clique CIS Now we have to prove correctness. We do this by proving both directions. That is Clique ⟺ CISClique\\iff CIS: Show that if CIS has a solution, then Clique has a solution: CIS returns the clique of size gg and an independent set of size gg if both exist. We have guaranteed a independent set of size gg by the above construction, therefore CIS will only return if there is a valid clique in GG, which is also the solution for Clique (since both demand a goal of the same size gg). Show that if Clique has a solution, then CIS has a solution: Clique will only have a solution if GG has a clique of at least size gg. But by construction, we’ve also added an independent set to G′G', which means that CIS is also guaranteed a solution. Thus CIS∈NPCIS\\in NP-complete by reduction. □\\square","date":"2023-03-30","permalink":"/blog/dpv-8-14-clique-independent-set/","summary":"Overview Problem Statement Prove that the following problem is NP-complete: given an undirected graph G=(V,E)G = (V, E) and an integer kk, return a clique of size kk as well as an independent set of size kk, provided both exist. Approach We call the problem CIS for brevity. First, we show that the problem is in the NP computational class. Next, we show we can reduce the known NP-complete problem Clique →\\rightarrow CIS. Finally, we provide a bidirectional proof to prove that the reduction is correct, which also proves that CIS∈NPCIS\\in NP-complete.","title":"Clique and Independent Set DPV 8.14"},{"content":"tl;dr There are great perks working for large tech companies, but there is a real threat of burnout. Tomorrow will be my fourth week since I’ve started working at Google for my summer internship. I’ll describe some of my experience, how I got here, and finally what I’ve learned so far. This article will likely be article 1 of a series of three going from beginning to end. This is the beginning to my reflection on the experience. Describing what it’s like to work at Google There is a lot of speculation of what it is like to work for a big tech company, or so-called FANG/MAMA companies (Meta, Alphabet, Microsoft, and Apple). I will take this opportunity to give my own opinion on what it is like to work in the industry here. I am not traditionally from the tech industry. I focused my professional career in the logistics industry and kind of found myself more and more interested in architecting and planning software. Give my LinkedIn a glance. I try to keep it as a living record as I climb the metaphorical mountain of career growth in America. {: height=“550” } I can confirm that a lot of the hype of working in big tech is warranted. Free food, laundry, gyms, massage chairs – it’s all there. However, I 100% tell you right now every amenity is earned. Software is HARD and it is a grind. Engineers earn a respectful living, but it is in no way handed to you. Imposter syndrome, burnout, having meetings from AM to PM are, unfortunately, all too real in the industry. I was surprised and taken aback a little by my colleagues. I’ve been here for such a short time, but the climate and openness of team members is already self-evident. People who get here are bright, hard-working, and take joy in teaching and helping others. I found this to be true when I ask questions, but also witnessed it observing Nooglers ask for help. “Here, it’s not like other companies where you have to earn everyone’s trust. It’s kind of like you start off with that trust and have to work to lose it.” Unlike other jobs where I felt an unspoken pressure in the office, here there is a sense of freedom I’ve never experienced while working. How did I get here? I met up with some 20 other interns for lunch at one of the larger cafes on the Sunnyvale campus. Introductions were passed around. After 5 or so people it seemed like everyone was a student at Yale, Carnegie, Columbia, Harvard, or some other variation. Comparing yourself to others quickly leads to imposter syndrome. I can best describe imposter syndrome with an allegory. There’s a scene in Parasite where the protagonist is wondering if he can fit into with the wealthy class that has adopted him into the fold. He questions his love interest if he belongs there, in the family’s beautiful home while a party goers merry outside. {: height=“550” } The scene is a great metaphor for imposter syndrome. The protagonist that has tricked his way into being associated with wealth, and now reflects on his place in the world. The wealthy family separated from him by the sheet of glass and his love interest, the anchor that has given him this window into this life, separated by a subtle line in the glass. While our lives are likely far from similar, the feelings this scene evoke speaks to me. Working with people with these amazing backgrounds solidified to me that they’re smart, but I shouldn’t automatically conclude that I’m (or anyone else) is not on the same playing field. On the contrary, it has allowed me to realize the only thing those schools and background does is give you some innate confidence or at least make others perceive you as smarter/more confident. The one lesson life has taught me, as corny as it sounds, is to be persistent. I failed to get into my master’s program the first time. I applied to about 200 jobs right out of college and only got into 1. Over and over again life has a way of putting your face in the dirt. But refusing to give up is a superpower. What have I learned so far? There’s a couple of key lessons so far in this internship: avoid getting complicit and never stop growing, know when to go and ask for help, communicate, and advocate for yourself, and most importantly, don’t be afraid to fail. There’s an art to failing, especially in software engineering. The key is to try and try again, iterating on your approach until you are making no progress. Once you reach this point you know it’s time to ask colleagues for input to solve the problem. The key to this process is short, feedback loops, where you fail often and quickly and learn from it. Failing just for the sake of failing is, well, failing. If you find places to make changes and get new error codes, well it’s fantastic news. Just like you. See you next time, space cowboy.","date":"2022-06-12","permalink":"/blog/interning-at-google-first-reflection/","summary":"tl;dr There are great perks working for large tech companies, but there is a real threat of burnout. Tomorrow will be my fourth week since I’ve started working at Google for my summer internship. I’ll describe some of my experience, how I got here, and finally what I’ve learned so far. This article will likely be article 1 of a series of three going from beginning to end. This is the beginning to my reflection on the experience.","title":"Interning at Google - first reflection"},{"content":"Have you ever gotten a captcha test that asks you to click all the busses or streetlights? Why such a specific question, like streetlights? You are actually training a machine to classify everyday objects! Classification allows a model to make assumptions. It is a generalization made to quickly make decisions using a precomputed set of rules and characteristics. For example, when a child mistakenly calls a cow a big dog, the child has just tried to classify the cow as a dog. A cow and a dog share traits (4 legs, fur, a mouth). However, when you point out that it is a cow, the child has to correct their model using narrowing techniques (dogs are small, cows are large, etc.). We can apply this same learning technique to an AI agent. A version space representation tries to narrow a classification class from broad to narrow enough to be useful for classifications. A version space creates two trees: a narrow and a broad tree. The narrow tree is the most specific classification of the concept possible, while the broad tree is the most general. The representation is fed positive and negative examples of what we are trying to train. On a positive test case (e.g., this labrador is a dog), we make the agent broaden its concept by giving it to the narrow tree to generalize. On a negative example (e.g., this cow is not a dog), the version space narrows its broad tree to specialize the model. We do this repeatedly until we’ve specialized and generalized from the examples provided and our two trees agree. The Version Space algorithm is efficient and powerful enough to take hundreds of cases and help to train an AI model to classify objects.","date":"2022-02-27","permalink":"/blog/a-brief-introduction-to-classification-used-by-ai/","summary":"Have you ever gotten a captcha test that asks you to click all the busses or streetlights? Why such a specific question, like streetlights? You are actually training a machine to classify everyday objects! Classification allows a model to make assumptions. It is a generalization made to quickly make decisions using a precomputed set of rules and characteristics. For example, when a child mistakenly calls a cow a big dog, the child has just tried to classify the cow as a dog. A cow and a dog share traits (4 legs, fur, a mouth). However, when you point out that it is a cow, the child has to correct their model using narrowing techniques (dogs are small, cows are large, etc.).","title":"A Brief Introduction to Classification used by AI"},{"content":"tl;dr Generate-and-Test is a human-like AI method that can solve complex problems by creating plausible states intelligently Give an infant some shapes and a shape sorter and watch them try to fit each shape into a slot. We call this method generate-and-test. A machine can use generate and test to solve various problems, using simple, human-like AI. This article will discuss using generate-and-test to solve the Tower of Hanoi with the fewest moves possible. The first step to this problem is figuring out how to represent it. The illustration gives a hint. Each block is either: On the table On another block Additionally, each block is either in its goal position or not in its goal position. At its most basic, generate and test is a simple algorithm. However, that won’t cut it here. We will experience combinatorial explosion if we try to generate all the possible states (1 block = 1 state, 2 blocks = 4 states, 3 blocks = 6 states). so we must endow either the generator or tester with some intelligence. We can do this by sub-dividing this problem into sub-goals. Here we want to get each block into its goal position and preserve it. To do so, we can add the following rules to our state generator: Do not move a block on the table to the table Do not move a “settled” block Do not move a block onto a “settled” block unless that block would also become settled We have made the generator smarter. It automatically rules out and limits our problem space. Let us do the same thing to the component of our code that tests a path. We can have our tester prefer to look at states with the greatest number of settled states (the sub-goal) and/or states with the fewest differences between them and the goal state. This can confine the number of paths we look at before moving to the next node. Now, these two components can efficiently solve the problem! This algorithm is very human-like in its approach. The AI agent, like us, will want to prioritize placing blocks into their final position. Just like a human, the agent will make moves that would get us closer to the goal without having to mess up the work we’ve already done!","date":"2022-02-20","permalink":"/blog/human-like-ai-with-generate-and-test/","summary":"tl;dr Generate-and-Test is a human-like AI method that can solve complex problems by creating plausible states intelligently Give an infant some shapes and a shape sorter and watch them try to fit each shape into a slot. We call this method generate-and-test. A machine can use generate and test to solve various problems, using simple, human-like AI. This article will discuss using generate-and-test to solve the Tower of Hanoi with the fewest moves possible.","title":"Human-Like AI with Generate and Test"},{"content":"tl;dr Representations are powerful problem-solving technique that provides perspective, and makes difficult problems easy Like humans, AI benefits from problem constraints and making abstract problems concrete We can make problems concrete using mental models. We make mental models by representing the problem How you frame a problem is everything. It can make a painless problem painful. However, a good mental model will make even complex, abstract problems concrete and simple to solve. The same is true in computer science and human-like AI. The rest of this article will use an example to illustrate mental models or semantic nets and why you should try to frame a problem in a way that aids rather than hinder its representation. An example problem: Wolves and Sheep A fun brain teaser: the wolves and sheep problem (or its many variants, such as missionaries and cannibals) asks how to move the two groups across a river without losing any members. The boat can hold up to two members, and may not cross without at least one sheep or wolf in the boat. If wolves outnumber sheep on either bank, then the sheep are eaten, and the game is lost. {: height=“550” } The graphic above is a great representation, but we can’t use images as code usually, so let’s make it even simpler! Say AA represents the origin bank of the river and BB the goal bank, If we have one sheep and one wolf we can model it as: A B 0 1 0 1 While this example is trivial, we have made the problem concrete enough to represent it using code. In Python, we can use a tuple, like ((B)ank, (s)heep,(w)olves). To make the model even simpler, we have sheep and wolves only count for the sheep and wolves on bank A of the river. We can deduce the number of sheep on bank B at any time (i.e., total sheep - bank A sheep = bank B sheep). Now we can observe all possible states in the problem: Send two wolves to the other bank Send two sheep to the other bank Send one wolf to the other bank Send one sheep to the other bank Send one wolf and one sheep to the other river bank (note you can mix groups so long as the boat is on the same side of the river) With our representation, we’ve reached the crux of the problem. Representing the problem is often the most challenging part of problem-solving. Once we can represent a problem, it opens up perspectives and possible solutions. A semantic network is created in the same way by, Representing the objects Representing the relations Coalescing to represent our knowledge of the problem Captures a transformation that maps an input to output, captures a relationship Now it is easy to use the transitory states of our model with a breadth-first search (BFS) algorithm to find a correct way of crossing the river. We use breadth-first search because we want to quickly rule out non-fruitful paths. In the worst case, we have to choose between 5 possibilities. (Depth-first search (DFS) would take much more memory on the stack). To make AI possible, we have to think of ways to quickly model problems to close the problem space and make the problem approachable as opposed to exponential problem space which is impossible to solve!","date":"2022-02-13","permalink":"/blog/framing-problems-and-answering-questions-human-thinking-and-ai/","summary":"tl;dr Representations are powerful problem-solving technique that provides perspective, and makes difficult problems easy Like humans, AI benefits from problem constraints and making abstract problems concrete We can make problems concrete using mental models. We make mental models by representing the problem How you frame a problem is everything. It can make a painless problem painful. However, a good mental model will make even complex, abstract problems concrete and simple to solve.","title":"Framing Problems and Answering Questions- Human Thinking and AI"},{"content":"tl;dr You are not your users Always, always conduct needfinding with actual/ potential users before touching code! Avoid bias by planning before gathering data Evaluate your prototypes in front of users What is Human Computer Interaction (HCI)? Human-computer interaction (HCI) is a relatively new interdisciplinary field involving technology, psychology, and engineering. It is a broad field whose scope includes or overlaps with UI/UX design, “smart” devices, and VR technology. HCI advocates for a structured, iterative approach to design. Ideally, a product will go through multiple stages. These stages present the product to actual users for feedback and evaluation. Designers should then use this feedback to make or brainstorm adjustments. The most important lesson that HCI advocates and the one takeaway you should remember is that: You are not your user. It is counterproductive to assume what your users want, need, or do not like because you are not your user. You have a different background than your users and may use the product differently than users considering your product. Herein lies the conflict with contemporary wisdom in Silicon Valley. HCI advocates a user-oriented process, while the common belief is to get a product out to market as fast as possible. What if I told you these two stances do not have to conflict? The rest of this article describes my understanding of HCI and its goal is to impart how you can use user feedback for a more user-centered design. An Overview of the HCI Design Process HCI advises following iterative and repeating design cycle: Needfinding. Determine what users want or need Brainstorming. Propose design alternatives that may address needs discovered in needfinding Prototype the idea Evaluate with users, and repeat The design process advocates for degrees of fidelity. You would not want to build a whole application only to receive poor feedback. Instead, the fidelity of the design should become more granular as the idea matures. I will discuss how the process plays out using an example redesign of the dndbeyond.com character sheet. How can needfinding fuel product ideas and designs Needfinding begins with defining a problem space, or a target domain. In the case of dndbeyond, the problem space was the character sheet. Next, we identify our target users. We chart relevant questions, including: Who would use this product? Why would someone use this product? What are the demographics of these users? What is their expertise level? What is their motivation? What are users’ frustrations in the problem space? What do they like? Should the product be easy to learn or cater to experienced users? The next step of needfinding is to find some actual users. Yes. Go and interview, survey, make observations, read forums, review missed clicks, etc. These methods yield valuable insights to the questions we have charted above. During needfinding be careful to outline potential biases you may inadvertently introduce. Everything from the design of survey questions, to your predisposition to come to a “correct” answer, may skew your results. For example, I conducted interviews with users of dndbeyond.com. I wanted to reduce bias, so I went with a mostly scripted interview, so all participants were asked the same questions with a similar tone. Furthermore, I quantified responses by creating a rubric and applying it to recorded responses. The results of my needfinding exercise found that users were using dndbeyond.com with a combination of tools (e.g., VoIP like Skype) and mentally occupied by a game setting (playing DnD and talking with a group of people). The interviews led me to conclude that the dndbeyond character sheet application needed the least possible cognitive tax (i.e., summarizing information and presenting relevant actions without obfuscation) and should work well with VoIP applications. Needfinding can fuel Brainstorming and product ideas The results of the needfinding exercise will naturally provide some constraints and goals when brainstorming. The interviews led me to conclude that the dndbeyond character sheet application needed the least possible cognitive tax (i.e., summarizing information and presenting relevant actions without obfuscation) and should work well with VoIP applications. While this can make brainstorming easier, one should also be aware of research into brainstorming. Some suggestions include: Come up with a set number of ideas as a goal. Make yourself reach this number. This helps because you can narrow down ideas later. Don’t critique ideas (“too silly, too expensive”) during brainstorming. At this stage, the goal is to put ideas onto paper. When stuck, use extremes (most expensive, cheapest, smallest, etc.) to help fuel creativity. On a team, give individuals time to brainstorm independently before setting up a meeting. During the meeting, write down all ideas and don’t discredit any. As your brainstorming session matures, you should be ready to pick an idea to prototype. Prototypes can vary in fidelity, However they must be presentable to users The goal of a prototype is to represent a product’s design to users for feedback. A prototype can be a drawing, a wireframe, a video, a pretend interaction, a version of the product, or even something else entirely. However, it must represent the product and give users a chance to interact with it. For example, when I worked on prototyping a redesign of the dndbeyond.com website I used a wireframe I created in Figma. The wireframe allowed me to present users with a mockup of my ideas to evaluate. Users must evaluate the prototype The evaluation phase is very similar to needfinding. However, this time the users are evaluating your prototype! Evaluate the prototype using the methods described in Needfinding (survey, interview). When evaluating your prototype, use the criteria you outlined during needfinding. Using the same criteria will help provide an objective grading of your prototype. It will also reveal where your prototype is better or worse than existing solutions. User feedback during the evaluation will help fuel your next iteration of the design cycle. In the case of dndbeyond.com, I used a survey to gather evaluating the information on my prototype. I found the results of this study to be mixed. Users found my prototype highly favorable in some regards but mixed or worse in others. and this is ok! This is the crux of the design process. If I were to continue wanting to explore improvements to the existing product, I would start the cycle again. HCI supports iteration. Designs should center on the needs of the users. While users do not ultimately decide how a product moves forward, they should always have input in the design process. Next Steps The design should continue to iterate through the design cycle. Conveniently, the evaluation phase gave us feedback on our prototype and can act like the needfinding stage, allowing us to move straight into brainstorming. If we are satisfied with the evaluation results, we should make a higher fidelity prototype and continue the process. Even when a product is released, the design process should be incessant, making improvements to a design throughout the lifecycle of a product. Making the Design Process relevant to fast-pace engineering Today’s dev environment is lightning fast. Often changes are made in a matter of days. Processes like Agile encourage fast development cycles. How then can we incorporate ideas from the field of HCI into modern software development? A/B testing: have one group of users use one version of the product, and another group of users use a second version via random chance. Then collect data about the two user groups and compare. Integrate the design cycle with Agile: after needfinding, have two teams run in parallel. The design team can run a week ahead in a sprint to give time to give data and results to the engineering team to implement The above methods help “caffeinate” the design cycle, while still allowing user feedback and a user-centered design approach.","date":"2022-02-06","permalink":"/blog/using-hci-to-supercharge-the-design-process/","summary":"tl;dr You are not your users Always, always conduct needfinding with actual/ potential users before touching code! Avoid bias by planning before gathering data Evaluate your prototypes in front of users What is Human Computer Interaction (HCI)? Human-computer interaction (HCI) is a relatively new interdisciplinary field involving technology, psychology, and engineering. It is a broad field whose scope includes or overlaps with UI/UX design, “smart” devices, and VR technology. HCI advocates for a structured, iterative approach to design. Ideally, a product will go through multiple stages. These stages present the product to actual users for feedback and evaluation. Designers should then use this feedback to make or brainstorm adjustments. The most important lesson that HCI advocates and the one takeaway you should remember is that: You are not your user.","title":"Using Human Computer Interaction (HCI) to Supercharge the Design Process"},{"content":"Motivation and Overview TimeTime was my first large, independent project. My motivation was two-fold. First, I wanted a project to help build my understanding of software architecture and the Android framework. Second, I wanted an application centered on privacy and gathering personal and work metrics. TimeTime took inspiration from an already existing application on the Android App Store. However, this application lacked desired features, stored data remotely, and locked premium features behind a subscription model. With my new goal in mind, I started to layout requirements and an initial design. Defining the project requirements I had a rough idea of my requirements going in because another app on the Appstore inspired me to make my own: Lockscreen prompts A log screen A statistics and graph screen Create activities with different colors and logos Categorize activities A localized database that allows export of data into CSV format These are a lot of features for someone learning Android. I made the mistake of trying to brute-force an application and create it without a plan. The result was bad code. The key takeaway from this project is always to have a plan. Even a poor plan is better than an absent plan. Designing the software I started by creating a wireframe prototype of my ideal app. The wireframe captured the look I wanted for each screen and component of the application. Then I needed to think about the software architecture of the app. What will time logs look like? How will they be stored in the database? What type of database will I use? How will the application talk to the database to retrieve and display logs? After some research, I decided to adopt a Model View Controller (MVC) approach. The user interacts with the app, the app interfaces through a controller class that abstracts communication with the database in my application (I used RoomDB with DAO support). Then when the app needs to display data from the database it uses the View class interface to make the appropriate calls to the database. Why is this important? It creates layers of abstraction. Layers separate responsibility while making the code maintainable. A user’s primary interaction with the application is to log their time. Each log is associated with an activity (sleeping), a category (health), and a duration (11 PM-8 AM). These requirements naturally gave a database schema. However, the issue of time is sticky. How should we store it? The application requires us to present the duration in a human-readable format, but this does not mean we should store it as a string. Storing the period as a string would make the database inflexible and cumbersome. Instead, I chose to store duration as a start and end epoch. Java has several good standard library functions to deal with epoch and human-readable format. The log class made use of these standard applications and abstracted any complexity between epoch and human-readable formats. The backend architecture of the app is in place. However, this does not handle what the user sees, just the organization of our program. In android, a given page is represented using fragments. Let’s walk through the application starting with the homepage. Designing the Front-end The wireframe I built earlier provided a solid foundation to build the frontend (colors, UI, etc.). After initializing a tabbed layout, I went to work on creating the home fragment. {: width=“250” } The home page needed to be populated by cards showing the user’s recent activities. Furthermore, it needed to be a RecyclerView (“infinite” scrolling) to provide efficient retrieval. The other requirement of the home page was to provide a way to log activities. I used a Floating Action Button (FAB) with a “+” on it. The FAB will also be present on most other fragments but with a responsibility corresponding to that tab. {: width=“250” } The activity and categories fragments are similar. They show the user the activities or categories they have in their database. Users can create custom categories or activities via the FAB. {: width=“250” } {: width=“250” } {: width=“250” } Finally, A statistics page aggregates the user’s database and presents data visualizations. {: width=“250” } {: width=“250” } Tidbits: Notifications and Lockscreen prompt I wanted the application to be opened maybe once a week by a user. Ideally, the user only interacts with the application via notifications. In TimeTime, there are two types of notifications: traditional and full-lockscreen. Both notification types must use a daemon thread and an alarm to trigger them. The challenge was to create a full-lock screen notification. This notification would “take over” the user’s lock screen to show the “log your time” screen, so the user can log what they’ve been up to without having to remember to open the application, or having to stop what they’re doing. I built this type of notification with Android’s PendingIntents.","date":"2022-01-30","permalink":"/blog/writing-a-time-management-android-application-timetime/","summary":"Motivation and Overview TimeTime was my first large, independent project. My motivation was two-fold. First, I wanted a project to help build my understanding of software architecture and the Android framework. Second, I wanted an application centered on privacy and gathering personal and work metrics. TimeTime took inspiration from an already existing application on the Android App Store. However, this application lacked desired features, stored data remotely, and locked premium features behind a subscription model.","title":"Writing a Time Management Android Application- TimeTime"},{"content":"tl;dr we use gRPC to make a distributed file system which can “share” a directory among multiple clients, keeping the directory in sync. gRPC simplifies client-server applications by taking care of infrastructure How can we write a server-client application that behaves similar to dropbox, google drive, and other cloud storage solutions? In other words, how can we create a system where the changes in a client directory are propagated to the rest of the system, including the server and other clients? We could code something from scratch, but it will be much easier and maintainable to use an established framework. Here I will use the gRPC framework. The gRPC framework is inspired by the procedure call paradigm first popularized by Sun RPC and others. gRPC is a modern framework that handles a lot of the legwork common in client-server paradigms. It’s fast, takes care of low-level infrastructure (network protocol, (un) marshaling data), and more). The framework will enable our server to communicate with all connected clients. This will make it possible to sync across the server and client directories, giving us a DropBox-like service (a distributed file system). Implementation details As always, it’s helpful to break down our requirements into manageable steps. At a minimum, the system should support the following: fetching a file from the server storing a file to the server deleting a file on the server retrieving the attributes of a file (created, modified, size) listing all the files on the server Implementing these requirements is easier using the gRPC framework. The framework abstracts away most of the complexity between client and server communication. It enables servers and clients to communicate analogously to making a function call. The way this works is via client and server stubs. To create a stub we have to specify an interface. gRPC handles this with the proto3 Interface Definition Language (IDL). A full example can be found HERE. Once we have defined the proto file, gRPC will use the specified interface to generate code when compiled. Overwriting the interface will allow gRPC to correctly mux requests to the correct server logic. That leaves us only responsible for implementing the logic behind each functionality. Next, we need to enable asynchronous support in the gRPC framework. At the moment, our server and client can handle synchronous traffic, but this is not capable of handling what we want. Again, gRPC makes this relatively simple. Our design will take advantage of this. We will make a daemon that runs on our clients. Whenever a change in the client directory is detected, a corresponding request to the server will be made. For example, if a client deletes a file in their directory, then a delete request should also be routed to the server. Similarly, the server should broadcast any changes to its directory to all connected clients. I chose to handle this problem by tracking what files are on the clients. Then, when a change occurs on the server, the server will send these details to all clients. Clients can then make a quick check of its local directory and change it to reflect the server’s most current state. The difficult part What if multiple clients are making changes that conflict with one another? For example, one client is trying to fetch a file while another is making changes to the file. Which file is valid? This is known as the readers writers problem. For the distributed file system to work correctly, we need to implement some exclusivity guarantees. Particularly, when a client is writing to a file and when the server is deleting a file. I implemented this by using reader/writer locks. Essentially a reader lock allows multiple entities to have access to a resource, while a writer lock allows only a single entity to have access. The server should associate each file with a lock, and any client that has the lock should also be noted. These locks in combination with a “lease” mean that a client making a write request can have a guaranteed amount of time where the client is given exclusive access. This lease must be timed to prevent the system from getting locked up on a misbehaving client.","date":"2022-01-08","permalink":"/blog/using-grpc-to-write-a-distributed-file-server/","summary":"tl;dr we use gRPC to make a distributed file system which can “share” a directory among multiple clients, keeping the directory in sync. gRPC simplifies client-server applications by taking care of infrastructure How can we write a server-client application that behaves similar to dropbox, google drive, and other cloud storage solutions? In other words, how can we create a system where the changes in a client directory are propagated to the rest of the system, including the server and other clients?","title":"Using gRPC to Write a Distributed File Server"},{"content":"tl;dr Caching makes huge performance improvements. Here we work on integrating a server-side caching application with a server To communicate between processes we have to use POSIX message queues, shared memory, and semaphores Motivation and Overview It is usually a good idea to cache the data a server will need in memory. The alternative is to always store data on storage or remotely. Retrieving from such secondary storage will take exponentially more time than retrieving from memory. Often this is counteracted by keeping frequently retrieved data in the main memory. However, our server program should not be monolithic. Instead, we can design our server to run a function when a request is made. The function will ask a caching process if the request is stored in memory. If the requested data is available, the caching process shares the data with the server process. Otherwise, the server can try to retrieve it from secondary storage. Implementation details The challenge of our requirements is in coordinating the server and caching applications. In fact, how does one even coordinate two separate processes? They do not share the same memory space and execution contexts. After all, this is the advantage to separating processes: isolation and security. However, we can bend the process isolation principle by asking the operating system. Let’s first focus on what exactly we need to achieve to implement a successful application: How does the server process ask the caching process for a file? How does the caching process respond to the server? Additionally, how does the cache send the data to the server? Importantly, all of these steps should occur rapidly, so this takes using files off the table to coordinate (otherwise, we may as well use secondary storage!). Kicking off the talks: asking for a request My design uses a message queue to make requests to the caching process. The POSIX message queue allows for processes to communicate on the machine. It also provides a convenient API and will block a thread. In this case, blocking a thread works to our advantage as it coordinates the cache process so that the cache process is asleep until it receives a request. My design uses a message queue to make requests to the caching process. The POSIX message queue allows for processes to communicate on the machine. It also provides a convenient API and will block a thread. In this case, blocking a thread works to our advantage as it coordinates the cache process so that the cache process is asleep until it receives a request. The server has access to this inter-process queue. Each message acts as a request. The request specifies the file and a shared memory segment to respond over (more on that in a second). Our cache’s main thread will be concerned with just checking this message queue. Worker threads will concern themselves with fulfilling requests. The data transfer process is orchestrated and synchronized with a pair of semaphores living in the assigned shared memory.Each message in the assigned shared memory. Talking back: how does cache respond and fullfil a request? The POSIX shared memory segments are initialized and assigned unique IDs at the server’s startup. When a client makes a request, the server passes the shared memory segment ID as a message to the cache over the message queue. Each memory segment has two semaphores. The worker thread will block on its semaphore (and the cache on the other when it finishes writing a response) until the cache increments it (unblocking the thread). The server’s worker thread will only be unblocked once the cache has finished writing its response (the data) in the shared memory segment. If there is a large amount of data, this cycle continues until all data is delivered to the server (the server can send this data off to the client iteratively as well). I found it best to structure the shared memory segments using a C struct. These structs make it possible to write data to the shared memory segment without making address adjustments (because the two processes likely map virtual memory addresses differently). Etc. POSIX inter-process communication paradigm is based on the “everything is a file” idea. And while message queues and shared memory segments are not really files, they are represented as such (on RAM, NOT disk!). That means they will continue to persist even after the programs that have initialized them stop running. We don’t want this to happen, especially in active development and testing. So as an added challenge, I had to write signal handlers that specifically take care of cleaning up these structures (along with other malloced memory). This consisted of changing the behavior of SIGTERM and SIGINT to first unlink and destroy these structures before ending their respective programs.","date":"2022-01-03","permalink":"/blog/coordinating-caching-in-multiprocess-applications/","summary":"tl;dr Caching makes huge performance improvements. Here we work on integrating a server-side caching application with a server To communicate between processes we have to use POSIX message queues, shared memory, and semaphores Motivation and Overview It is usually a good idea to cache the data a server will need in memory. The alternative is to always store data on storage or remotely. Retrieving from such secondary storage will take exponentially more time than retrieving from memory. Often this is counteracted by keeping frequently retrieved data in the main memory. However, our server program should not be monolithic. Instead, we can design our server to run a function when a request is made. The function will ask a caching process if the request is stored in memory. If the requested data is available, the caching process shares the data with the server process. Otherwise, the server can try to retrieve it from secondary storage.","title":"Coordinating Caching in multi-process applications"},{"content":"tl;dr We start build-up from our starting point of a simple echo-client and server, to a file-server Make use of IPv4/IPv6 agnostic TCP sockets Create a simple HTTP-like protocol to standardize and parse client requests Overview Overall requirements: IPv4/IPv6 agnostic, TCP, multi-threaded (server can service multiple clients simultaneously, parse and respond to requests in C (i.e., memory management, buffer allocation, byte parsing), implement a simple HTTP RESTful client-server application. The server needs to receive and parse file requests from a connected client. Once the request is verified the server needs to serve the file’s data to the client. Moreover, the server should handle multiple, concurrent connections. These specifications are quite challenging if taken as is. However, if we break down the problem and build back up we can come to a good solution. Let’s start from an echo-client and echo-server. Echo this: Sockets and such Socket communication can be broken down into a few steps. From the server’s perspective to communicate with a client, we want to: allocate a socket, bind that socket, listen for incoming connections, and accept connections (allocating a new socket to that client). Similarly, from the client’s perspective, we want to allocate a socket, try to connect to a host, receive a response. Several resources explain how to create an echo server and client application (I recommend this book, but this site is excellent as well). We need these sockets to be IPv4/IPv6 agnostic. Thankfully, from the standard library has an interface to help with this problem. The server needs to bind a socket able to service IPv4 and IPv6 TCP clients. Is there a way to do this succinctly without hacky or branching code? I will be using the getaddrinfo function with the AI_PASSIVE flag to ensure our server can handle both protocol types. Similarly, the client should be capable of connecting to either IPv4 or IPv6 servers. Similarly, the client will also use the getaddrinfo function to determine what socket to allocate for (what is the host’s protocol?). We are careful to use the AF_UNSPEC flag to let getaddrinfo know we want to wildcard our address family (IPv4/IPv6). Sending a message is pretty simple. The client can call the send function with its newly allocated socket. Note that the send function does not guarantee the entire message can be sent in a single call. To ensure we’ve sent the entire message, we call send iteratively. We stop the total sent bytes is equivalent to the size of the message. A nearly identical process plays out on the server-side when we call the rcv function iteratively. Static File Server The server and client can send and receive strings. We can make this a little more useful by serving connecting clients with a file instead of just echoing their message. Not much needs to be changed. We alter the server so that it now sends a stream of data. This stream comes from the file. Similarly, we modify the client, so it receives data iteratively from its connected socket until no more data is received. The client should write this data to its local directory, saving it as a new file. Dynamic File Server: taking client requests OK. Now we have a server that serves a single static file. This is not very dynamic. Let’s instead have the server take a request from a connected client. This means we will need to have the server receive and parse requests. Whenever two parties are talking to one another, they need a set of rules. In a real web communication context, this is something like HTTP. Here we will use an HTTP-like interface. The result is that communication is structured. client requests with a predictable request format the server parses the received string, validates the request, and responds with a status If validation is successful, the server proceeds by transferring the requested file’s data the client is disconnected and should connect again to make another request Recall, this project is written in C. We send strings over the TCP socket via single char bytes. We put these characters into an array, then start to parse it. I found that using functions in C’s standard library made the project much simpler than writing my own. I made great use of the strtok function. Depending on the results of the parse and validation, the server responds to the client with either an OK, ERROR, or INVALID status. The client will block until this status message is received. On an OK status, the client will receive the data of the file in the same manner as the earlier implementation. Concurrency: Serving and requesting files simultaneously We’ve gone from a simple echo client and server to a full-fledge server capable of serving files to clients. However, there is a final limitation. This server is only capable of serving one client at a time. What do we do if more than one client wants to connect and receive a file simultaneously? One option is to have the clients queue up in a line and wait their turn (Imagine having to wait your turn to watch a YouTube video!). This is not a very good option. Another option is to have the server launch another copy of itself when accepting a client. This copy of the program will handle the client while leaving the main instance of the server free to accept more clients. However, there is a lot of overhead associated with creating copies of programs. This option would work but would scale poorly. The third option, which is what I chose, was to make the server multi-threaded. A multi-threaded server would have its main thread accept incoming clients, then load these clients into a queue. The queue, in turn, would be handled by a child thread that would fulfill the request. I implemented this using the pthread’s library. A callback function is registered with each thread. The function kicks off the client-handling portion of our implementation. These threads would sleep until the main thread signals that a client needs to be served.","date":"2021-12-30","permalink":"/blog/building-a-concurrent-tcp-file-server/","summary":"tl;dr We start build-up from our starting point of a simple echo-client and server, to a file-server Make use of IPv4/IPv6 agnostic TCP sockets Create a simple HTTP-like protocol to standardize and parse client requests Overview Overall requirements: IPv4/IPv6 agnostic, TCP, multi-threaded (server can service multiple clients simultaneously, parse and respond to requests in C (i.e., memory management, buffer allocation, byte parsing), implement a simple HTTP RESTful client-server application. The server needs to receive and parse file requests from a connected client. Once the request is verified the server needs to serve the file’s data to the client. Moreover, the server should handle multiple, concurrent connections.","title":"Building a Concurrent TCP File Server in C"},{"content":"tl;dr OMSCS Graduate Introduction to Operating Systems will give you a wide breadth into modern operating systems Exams are over-weighted Projects were fun, but can be challenging coming from a less experienced background GIOS Fall 2021 Review Coming from an economics background with Java and Python experience, GIOS was a plunge into the deep end of the swimming pool. There are two parts to the course: Lectures (pretty good, but old, amended, and in some places confusing) Projects The projects are always tangent on the lectures, but you CANNOT solely rely on lecture material to complete them. They are challenging for someone with not much C/C++ experience, but they were also rewarding and enjoyable. If you decide to take this class, you are in for a challenge—but you will not be at it alone. This class has one of the best online communities in the program, thanks to strong TA’s and participation on slack. Takeaways I can code in C. I can confidently describe what an operating system is responsible for and generally go into specifics. I got a taste for distributed computing and how that works. I understand threading, inter and intra process communication using sockets, shared memory, signals, etc. I feel more confident in taking on the rest of the systems specialization. Where it could have been better Lectures are excellent (info is presented concisely for the amount of material) but can be better in some spots. Exams are weighted heavily. Exams are short. Each question is worth roughly the same as a project’s readme for your overall grade. Papers are good but don’t play a huge part in exams. You ought to read them, but there is little incentive grade-wise.","date":"2021-12-30","permalink":"/blog/omscs-gios-review/","summary":"tl;dr OMSCS Graduate Introduction to Operating Systems will give you a wide breadth into modern operating systems Exams are over-weighted Projects were fun, but can be challenging coming from a less experienced background GIOS Fall 2021 Review Coming from an economics background with Java and Python experience, GIOS was a plunge into the deep end of the swimming pool. There are two parts to the course: Lectures (pretty good, but old, amended, and in some places confusing) Projects The projects are always tangent on the lectures, but you CANNOT solely rely on lecture material to complete them. They are challenging for someone with not much C/C++ experience, but they were also rewarding and enjoyable.","title":"OMSCS GIOS Review"},{"content":"A readable summary of how an operating system facilitates multi-threading and how it works. This series of articles will cover key questions about how an Operating System works. After you read it, you will walk away knowing what the OS does behind the scenes to make your life easier when creating multi-threaded applications. You won’t need much of any background to read this article, but it will help if you are familiar with a low-level language, like C. If you want to learn more, the end of this article provides my sources and what you can use in your own studies. Make sure to check out part one. Processing a Process In part one, we used the terms “process” and “application” interchangeably. This is not entirely correct, as you will see. An application is represented as one or more processes. A process, by definition has its own resources and data, the most basic unit of work on the user level. Recall that the OS uses processes to achieve its goal of modular and isolated programs. Note, this article will be more in-depth than part 1. If anything looks confusing, feel free to skip it. The important stuff is the conceptual level and why things happen. You can always look up the details! Processes At its core, a process represents a state of execution. The OS has to keep track of a process’s state to manage it. Each process has a corresponding Process Control Block (PCB) that the OS can track its state. A PCB has: Program counter, a counter held in the CPU that tracks what line of execution the program is on A Process ID A Virtual address space, the OS will allocate each process with memory, but to the process, this allocation looks like the entire machine’s memory! In reality, the OS has abstracted and decoupled physical memory to virtual memory. The effect is simplified memory management A Stack pointer, part of a process’s state is the state of its stack. A stack is simply a place in memory that lets a program track what data it currently is using in its scope A Heap, a section of memory that holds dynamically allocated data for the process Static data/text, loaded in when the process first launches, does not change throughout the execution CPU register state, the state of registers when the process is working, may change throughout the execution It is important to remember that processes are modular. Each process has ownership of its resources. Recall that one of the operating system’s missions is to guarantee that process isolation and security. Process Control Block (PCB) The OS has to track all of this information along with some scheduling information with each process. Operating system engineers came up with the process control block (PCB) to do just that. For example, the program counter is initialized to the first instruction if the process is new. These fields are updated when they change (e.g., program counter pointing to the next line). The operating system is responsible for updating the PCB. The PCB is used to track the state of execution of any given process. No single process is allowed to dominate the CPU, so the OS must have the ability to save and restore a process as it gets dispatched and preempted to the CPU. The PCB enables this so-called context switch to occur. Context switches The operating system takes a hit to performance each time a context switch occurs. Context switches are expensive. First, The OS is obligated to use CPU cycles to store the current processes information into its PCB and load the new processes state from its PCB. Second, a context switch will result in a cold cache (see part 1), slowing down execution. It is the interest of the operating system to avoid context switching whenever possible. What do you think are some policies an OS can use to avoid context switching? When would the OS be forced to context switch? Keep context switching in mind as you read the rest of the article. Process lifetime Each process goes through this life cycle. Let’s discuss what each stage entails: new: Process gets created; the OS allocates and creates a process control block for the process and its resources (heap, stack, PCB) ready: The scheduler decides to queue the process to the CPU. The scheduler maintains the queue. running: The process is running on the CPU. The CPU can only run one thing at a time. On an interrupt, the CPU will no longer run the process. Operations that require I/O access will result (e.g., system call like read()) in the process being moved to waiting. The scheduler decides when to context switch. waiting: Processes here are completing some longer event. Usually, this is handled by the peripheral (e.g., the OS will request the data from the hard drive). The scheduler will move the process to ready when the operation completes. terminated: A process that completes and exits or one that results in an error code. What role does the OS scheduler play? The scheduler is vital for moving processes on and off of the CPU. For this to happen, the OS needs to: Preempt: interrupt and save the current context of the executing process Schedule: determine what to run next, depending on the operating system’s scheduling policy Dispatch: send the chosen process to the CPU and initiate a context switch Naturally, the next question is how often should the scheduler run? The answer is it depends on the OS’s policies and the state of the process. For example, if the process blocks (i.e., waiting on something to finish like saving to a disk) and it takes less time to context switch than the blocking operation, it may make more sense to go ahead and run the scheduler for a context switch. Note this all affects CPU efficiency, or (total time doing user work)/(total time doing user work + total time doing OS work). Can processes communicate with each other? Recall that one of the guiding principles of OS design is the modularity of user processes. Can we keep the modularity of processes while allowing processes to communicate? Engineers designed inter-process communication (IPC) to facilitate processes to communicate. IPC mechanisms do not compromise a process’s isolation/modularity. The first type of IPC is called Message-Passing. The OS opens a channel of communication for the two processes (like a shared buffer). Each process can write to and receive from the shared channel to communicate. The OS acts as a mediator and provides a user interface. The downside is that because the OS is involved, there is a hit to performance. The second IPC method is called Shared Memory. Here, the OS establishes a shared channel and maps it into each of the process’s address spaces (memory). This makes communication fast, but the OS does not mediate, so it is up to each process to create its own read/write methods. Threads Before threading, concurrent programming occurred via multi-process applications. That is, the application makes a fork or exec call to launch a child process. Every process needs to be isolated and endowed with its resources by the OS. Processes are expensive. And it was common for applications to run copies of themselves. These copies had the same variables, code, and execution flow. With multi-threading, multi-process applications could shift to a new paradigm of concurrency. Sun OS was one of the first operating systems built around multi-threading and multi-CPU usage. Its design continues to remain relevant and is what many modern practices can be traced back to. You can think of a thread as a miniature process within a process. But unlike processes, threads share their virtual memory space with the process. Each thread is a context of execution. Threads can access common resources in a process. However, threads need to track their own: Program counter CPU register state Stack Pointer You may already be seeing a similarity with process control blocks. If you did, good catch! Threads track their needed information by taking from the overall PCB into their data structure. Threads are super useful for several reasons. First, they enable parallelization (multi-tasking). First, Threads divide tasks to work on a problem concurrently. Second, threads enable specialization. Recall that part of the issue with context-switching was the cache going cold. In multi-threading, this issue is less severe because threads are likely to be using similar resources. So, switching between threads is less likely to result in a cold cache. Multi-threading generally trumps the multi-processes paradigm because a multi-threading application will have lower resource overhead, easier synchronization, and cheaper context switching. Are threads useful on single CPU machines too? Yes! Because threads share memory, context switching is cheaper. Furthermore, if one threads blocks by doing an expensive operation, we can hide the application’s latency by switching to another thread! Switching threads is inherently cheaper than switching processes. Thread lifetime Threads creation is done through a parent thread (you can think of a process as a single-threaded application). The parent initializes a child thread with a function (depending on the library). where should the thread begin its point of execution? The child thread will initialize with a data structure that represents the new state of execution. The child thread goes ahead and executes concurrently with the parent thread. Generally, the child thread will exit first. When the child thread finishes its work, it may go ahead and return some result. An easy way for the parent thread to get those results is to use a join call. The join function will result in the parent thread blocking (waiting) for the child thread to complete. Once completed, the result associated with the child thread is returned to the parent via the join. If there is only one child thread and one parent thread, and they do not use the same resources concurrently, then this is it! We have a concurrent program. However, an application with shared a resource (e.g., an array that all the threads want to access, etc.) and concurrent access of that resource, needs to consider synchronization constructs. Synchronization and Parallelization Synchronization is a way of coordinating multiple points of execution. Synchronization must guarantee the correctness of a program. There exists a multitude of synchronization constructs, but today we will only discuss mutexes and conditions. Mutexes (locks) In parallel programming, there is no guarantee of sequentiality. For example, if we told one thread to write a document, and another to read it, the reading thread will likely read incomplete data. Locks (mutexes) are a way of guaranteeing sequential, exclusive access to a shared resource. A resource that is locked is only accessible to that thread. All other threads are placed in a line to wait for their turn. What happens to another thread that tries to access a locked resource? You can think of a mutex as a lock with some handy features. It tracks if it is locked, who the “owner” of the lock is, and any threads that tried to access the lock while it was locked. Threads that encountered a locked mutex are put to sleep in a queue. When the lock is released (unlocked), the mutex will wake up the waiting thread on its queue, where it can go ahead and try to obtain the lock again. Neat! Mutexes make managing access easy. They are cheap to initialize and guarantee exclusive access to a resource. Exclusivity essentially makes the region of code (a critical section) protected by the mutex single-threaded. Code protected by a mutex should be small, fast, and only have to do with accessing/modifying a shared resource (e.g., a data structure, shared resource, etc.). Don’t forget every lock should have a corresponding unlock! Check out your language’s multi-threading library for interface specifics. C has pthreads, Java has Thread,… What happens if you have just left your friends home with their car keys and your friend has your house keys? In programming, we call this a deadlock situation. Mutexes are powerful. Powerful enough to make a program get stuck. Avoid allowing a thread to take a lock and later have to take another lock. This makes your code vulnerable to having a thread waiting for another thread to give up its lock, while that thread is waiting for the first thread to give up theirs! Condition variables Sometimes you only want threads to run only when a condition occurs, or another thread tells it. The condition construct signals when threads should start working. You will always want to associate a condition variable with a mutex. First, the thread has to hold the mutex. Then, we check if a condition is met (e.g., while, if). If this condition is not met, we tell the thread to wait using the mutex and condition. The thread then unlocks the mutex and is put to sleep. When the condition variable is signaled, sleeping threads can be woken to go ahead and work. There are two signals: signal(condition), wake-up a single sleeping thread associated with the condition broadcast(condition), wake-up all sleeping threads associated with the mutex It is often preferable to use a while loop to check on the condition because a while loop will provide several assurances. First, the while loop can deal with multiple threads. Second, when we use signal, we can’t guarantee the order to which waking threads will access the mutex. Finally, the while loop safeguards cases where the condition can change. Something to watch out for with condition variables is waking a thread, just to have it go back to sleep on the wait. This wake-immediately-sleep cycle is called a spurious wake-up. Spurious wake-ups are a waste of CPU cycles and can usually be solved by reordering mutex locks and unlocks.","date":"2021-11-01","permalink":"/blog/an-introduction-to-thread-concurrency-a-os-perspective-part-2/","summary":"A readable summary of how an operating system facilitates multi-threading and how it works. This series of articles will cover key questions about how an Operating System works. After you read it, you will walk away knowing what the OS does behind the scenes to make your life easier when creating multi-threaded applications. You won’t need much of any background to read this article, but it will help if you are familiar with a low-level language, like C. If you want to learn more, the end of this article provides my sources and what you can use in your own studies. Make sure to check out part one.","title":"An Introduction to Thread Concurrency- a OS Perspective (Part 2)"},{"content":"A readable summary of how an operating system facilitates multi-threading and how it works. This series of articles will cover key questions about how an Operating System works. After you read it, you will walk away knowing what the OS does behind the scenes to make your life easier when creating multi-threaded applications. You won’t need much of any background to read this article, but it will help if you are familiar with a low-level language, like C. If you want to learn more, the end of this article provides my sources and what you can use in your own studies. Make sure to check out part two. What even is an Operating System? On a technical level, an operating system is a layer of software that sits above the hardware layer of a computer. Typically, it is the only piece of software on a system that has the privilege and power to manipulate the underlying hardware. File systems, networking, and disk access are all managed by the operating system. Other applications can not access the underlying hardware. Instead, they have to ask the OS for permission. In most operating systems, this means that the OS provides an interface for working with hardware. As a programmer, you don’t have to worry about things such as hard disk drivers. Instead, you call to open(), and the OS kicks off the rest. Besides being an arbitrator to the hardware layer, the operating system has two more important responsibilities. First, it must assure that all applications are modular (i.e., isolated) from each other. Modularity means that applications should each essentially think they have the computer to themselves. Why? Because if every program were able to see every other program, there is potential for accidental (or malicious) interactions that could cause the whole system to crash. For example, if chrome had access to every other program’s memory, can you imagine what security risks this could cause? What if a virus could access or overwrite what was in memory for all applications on a system? Hold on! what is a memory?! Is it the 256 GB I have on my computer? No. You can think of memory as a lightning-fast phone book. Applications that are running have a bunch of addresses on hand that they use to look up resources an application is using. These resources are usually small enough to all be in memory (RAM). An operating system must manage, allocate, and abstract the underlying resources of a system. The abstractions an operating system provides are vital for supporting modularity and simplifying the complexity of underlying resources. Abstractions, Mechanisms, and Policies You may be thinking, why are abstractions even a thing? My application should be all-knowing and just work off the system’s metal! Well, if that were the case, we would have a lot tougher time programming between machines. The software would have to be made specifically for one system (or class of systems). Lack of compatibility between machines was standard practice up until the late ’80s! (i.e., analogous to PlayStation and Xbox rather than Windows XP and Windows Vista) Abstractions let processes not worry about how much memory is on a system or what kind of ethernet is on the motherboard. It also allows engineers to upgrade the underlying hardware/software of these components without affecting existing applications. For example, when phones made the big switch from 3G to 4G in the 2000s. Newer phones were able to support both networks while running older applications. As far as the applications on these phones were concerned, a network connection was a network connection! So, how does the Operating system manipulate the state of the hardware? How does the OS allocate memory to a process? or dispatch a program to the CPU to run? These processes are very mechanical because they work in a set way, so we call them mechanisms. Some systems may find it best to, for example, give the CPU to one process for a long, long time, while others might find it best to keep switching between processes. Varying ways of using mechanisms is an example of a policy. Policies manage how the system decides to use its mechanisms. Different machines will have different use cases (e.g., a home PC has different requirements an IBM mainframe!). Operating Systems seem complicated- what are their Guiding Principles? Optimize for the common case. I hinted at this in the last section. OS designers have to consider what the system will be used for, its requirements, and its users/stakeholders. It is impossible to optimize for all cases, so designers have to implement their policies around these constraints. Separate mechanisms from policies. Engineers need to offer mechanisms that are flexible enough to fit many types of use cases. Separating mechanisms and policies makes mechanisms more flexible. Flexible mechanisms enable different policies that are themselves now flexible enough to be changed by a user setting or circumstance. What challenges could arise if policies and mechanisms weren’t separated? Can you think of any examples of both cases in/out of the computing world? Phew, that was a high-level section. Let’s get more concrete! Access, Privilege, and Hardware User applications can never access hardware. There is a clear separation between system (privileged), kernel level operations, and user level (un-privileged) contexts. Hardware also plays a role. The Trap A machine’s hardware even facilitates the distinction between user and privileged access. The CPU has a special switch (a bit) that is flipped on/off depending on the system’s access level. If the system is on a user level, the switch will be off. Then when an application attempts to access hardware, the CPU will check the status of this switch. If it is off, it acts as an alarm, and a hardware interrupt occurs to hand control over to the Operating System. The OS then decides to continue or terminate the hardware procedure. This describes a boundary between privileged and user modes. What does crossing the boundary look like? How do applications even get to save stuff on the machine? The trap is just one way the boundary can be crossed. Other ways this crossing can occur is through: traps system calls signals In each case, control is handed from the currently executing process to the corresponding handler. Generally, the handler is implemented by the operating system and lets the OS have control again. The elephant in the room throughout this article, I have made hints that the CPU doesn’t run more than one thing at a time. A big challenge in designing an OS is efficiently running programs on the CPU. Generally, whenever the CPU is running an OS process, we consider it inefficient. Time used on a system process is time that could have been used on a user’s tasks. The handler has the instructions needed to give the application the resource is requested (such as reading/writing to a hard drive). There is friction in the flow of execution and who controls what. The important thing to remember is that it is the job of the operating system to facilitate user processes access to hardware resources. The downside to handing control over (and crossing the privilege mode boundary) is the processing time. The operation is inherently expensive. Handing execution control back to the OS means that there is a switch in the execution context. The CPU has locality. That is, when the CPU runs a process, its resources are loaded into the CPU itself in the form of a cache. The swap in control means that the cache goes cold because the resources loaded into the CPU are no longer relevant. What do you think a hot cache is? Operating systems get their own fancy name for their interface: System Calls Let’s expand on what a system call is and what it looks like when we cross the privilege boundary with this interface. The user-level process is happily chugging away- It makes a system call to access the hard drive (the application will make sure to have somewhere to save the result) Control is passed to the OS in privileged mode. The OS’s handler performs the operation System call completes, execution context changes back to the user-level (un-privileged), and control is handed back to the user application (results save in the defined space the process made in step 1). Again, this process is expensive. Not only does the CPU go cold, but if the system call is slow, the process may have to halt until that completes (think of a loading screen for a game). More operating systems than just Windows and Macintosh! Ok, let’s make a quick detour as to what types of operating systems there are. Modular Most operating systems modern computer users are familiar with modular operating systems. Macintosh, Windows, most Linux distros (Ubuntu, etc.) are in this category. Modular operating systems are characterized as relatively complete OSs that also allow users to install additional software. The modularity of the OS makes the system easier to maintain, while also having a smaller footprint than other types of operating systems. The disadvantages here come from the installable software. Software installation can introduce unintended interactions. Furthermore, a modular OS has to have a level of indirection (i.e., applications have to go through an OS implemented interface to work), which impacts performance compared to the next class of OS. Monolithic Historically, the most popular operating system. This type of OS is the grandpa of operating systems. Here, the operating system is the whole package. It includes all the applications the user will use as a part of the system. These operating systems did allow users to run files from a disk or other peripheral device but did not allow installations. Commodore is a great example, but also mainframes and even some web servers today are still considered monolithic operating systems The advantage of this design is that all optimizations can be made since engineers know exactly what will be running on the machine. The disadvantage of this system is that there is no ability to customize or portability (applications are built for one OS and one OS only). Furthermore, these systems have higher overhead because of the completeness of the package. They can also be difficult to maintain. Do you think your smartphone’s operating system is monolithic or modular? Why? Microkernel This type of operating system is super tiny compared to the others. Its size makes it ideal for embedded devices because the entire OS is verifiable. Because of its size, a microkernel OS ships slim. It lacks many of the convenient interfaces that a modular OS would provide. Instead, it expects its user to implement whatever additional functionality the device will need. This means that this system experiences more frequent user/kernel crossings. Another disadvantage is its portability (applications have to be designed for that OS), development complexity (you have to implement what the OS would normally have available to you). Summary and Readings This article is part one of a multipart series on Operating systems. Here you learned the types of operating systems, what an operating system is responsible for, and made initial conceptualizations of how an OS manages and organizes user applications and resources. In part 2, we will introduce processes and threads. Resources and Further Readings Arpaci-Dusseau, R. H., \u0026 Arpaci-Dusseau, A. C. (2018). Operating systems: Three easy pieces. Arpaci-Dusseau Books, LLC. Donahoo, M. J., \u0026 Calvert, K. L. (2009). TCP/IP Sockets in C: Practical Guide for Programmers. Elsevier. http://public.eblib.com/choice/publicfullrecord.aspx?p=428534 Hall, B. “Beej J. (2020). Beej’s Guide to Network Programming. beej.us. https://beej.us/guide/bgnet/html/#connect Kerrisk, M. (2010). The Linux programming interface: A Linux and UNIX system programming handbook. No Starch Press. ‘Till next time space cowboy – Alex","date":"2021-10-10","permalink":"/blog/an-introduction-to-thread-concurrency-a-os-perspective-part-1/","summary":"A readable summary of how an operating system facilitates multi-threading and how it works. This series of articles will cover key questions about how an Operating System works. After you read it, you will walk away knowing what the OS does behind the scenes to make your life easier when creating multi-threaded applications. You won’t need much of any background to read this article, but it will help if you are familiar with a low-level language, like C. If you want to learn more, the end of this article provides my sources and what you can use in your own studies. Make sure to check out part two.","title":"An Introduction to Thread Concurrency- a OS Perspective (Part 1)"},{"content":"This article will argue that the progressive tax system is more equitable than a flat-rate tax system. First, we describe each tax system in the simplest terms possible. Flat Tax In a flat tax system, everyone, no matter their background, pays the same tax rate. In the USA, a real-life example is a sales tax for a region. In a flat tax system, no matter how much money you spend at a store or how much money you make, you will pay the same flat percentage. For example, if the tax rate is 10% you would owe $10 on a taxable amount of $100. Progressive Tax In a progressive tax system, just like a flat-rate tax, everyone pays the same percentage on the taxable amount, but the taxable amount is broken down or “categorized.” In the USA, this is how federal income tax works. How is money categorized? Imagine applying a progressive tax to a shopping situation: you would like to buy a $100 item. The tax rate here is 10%, so you pay $10, exactly like in a flat tax system. Ok, so what is the difference? We can apply the progressive tax system to a more expensive example to make the difference obvious. A $200 item under a progressive tax could still take the first $100 and tax it at 10% ($10 paid), then it may take the next $50 and tax it at 20% (another $10), then, finally, the last $50 is taxed at 30% ($15 paid). The total tax paid is $35 on the $200 taxable amount. The $200 example illustrates that a progressive tax system divides taxable amounts into brackets, with each subsequent tax bracket increasing in rate. Regressive Tax I will not discuss the regressive tax system any further after this section. The inequality of the regressive tax system is a fair bit more obvious. A regressive tax is the same as a progressive tax but flipped. That is, the higher tax rates come in the first buckets and progressively decrease. Using the $200 purchase as an example: the first $100 is taxed at a 30% rate ($30), the next $50 at 20% ($10), and the last $50 at a 10% tax rate ($5), for a total of $45 paid. A quick aside I mentioned buckets/brackets and example tax rates in the previous examples. I want to add a caveat, the buckets and the tax rates are arbitrary. That is, the tax rates and bracket are flexible and often change. Another aside is that there is a popular belief that accepting a pay raise will “push them into a higher tax bracket.” It is important to remember that these buckets are independent. Money gets passed through them at all stages, and you never pay more than you earned (in the case of an income tax). In other words, you will always get a portion of each additional dollar, no matter what bracket that money goes into. It is always better to take more money if offered. Why is the Flat Tax not an Equitable Tax Policy? We have established a basic definition of each system. A flat tax charges the same rates to everyone. A progressive tax system breaks money up into brackets, with each bracket taxed at a different, increasing tax rate. A regressive tax system also breaks money into tax brackets, but the higher tax rates occur at lower tax brackets. We now discuss flat-tax and progressive tax systems as they pertain to income. We will show why the flat tax rate system is less equitable to lower-income taxpayers using an example. I built a simple spreadsheet that illustrates the progressive tax system for 4 set buckets (these buckets are not changeable in this example!). For the progressive tax system: The first $500 in this system is tax-free The next $1000 is taxed at 6% The next $5000 is taxed at 15% Anything beyond that ($6500\u003c) is taxed at 25%. So only income more than $6500 is taxed at the 25% rate. These tax brackets work better with incomes ranging from $3,000 to $15,000 because there are only four tax brackets (real-life systems have many more brackets). Nonetheless, this system will work as an illustration of how inequitable the flat tax system is. We look at a $10,000 earner (Person A) and a $15,000 earner (Person B) under both systems. We plug into the calculator the incomes, and we are left with the following: I set up the example so that both the flat tax and the progressive tax systems generate almost the same revenue. As you can see, in both tax systems, the higher earner pays a higher total tax. Here is the vital bit, the meat of the argument: we can see in the graphs above that, all else equal (i.e., revenue generated), the flat-tax system taxes poorer earners more of their income by percentage than the wealthier earner. That is, that when looking at the percentage of the income tax, there is more burden on the lower-income earner. The tax burden is compounded further when you consider that the poorer earner is also going to spend more of their income as a percentage on necessities, reducing their real income even further, if you consider necessities as a “tax” you can already see how unbalanced the flat tax system becomes. With necessities In this example we add a flat cost of $500 to both person A and person B as a stand in for basic expenses (food, hygiene): Conclusions The heart of the argument against a flat tax is: Compared to a progressive tax, a flat tax places a higher burden on lower-income taxpayers. Lower-income earners will have to use a higher percentage of their incomes to buy goods when compared to a progressive tax that considers that lower-income earners must use a threshold amount of money to fulfill basic needs of life. As illustrated in our example, flat tax results in smaller taxes as a percentage of income for the wealthy. The flat tax is a less equitable tax system. All three systems can, in theory, charge lower amounts when compared to other systems. Proponents of either the flat tax system or the regressive tax systems may use this to make convincing arguments for their tax system of choice. Be wary of this argument. To generate the same tax revenue as the progressive tax system inherently means that lower and middle-income earners will carry an inequitable tax burden compared to higher-income earners. A policymaker can always propose a lower tax to begin a system, but as the needs of the budget increase, they will have to increase taxes, and that new great rate they offered has ended up being a bait and switch. ‘Till next time space cowboy – Alex","date":"2021-06-23","permalink":"/blog/a-look-at-the-flat-tax-and-progressive-tax/","summary":"This article will argue that the progressive tax system is more equitable than a flat-rate tax system. First, we describe each tax system in the simplest terms possible. Flat Tax In a flat tax system, everyone, no matter their background, pays the same tax rate. In the USA, a real-life example is a sales tax for a region. In a flat tax system, no matter how much money you spend at a store or how much money you make, you will pay the same flat percentage. For example, if the tax rate is 10% you would owe $10 on a taxable amount of $100.","title":"A Look at the Flat Tax and Progressive Tax"},{"content":"A high-level introduction to sockets, or what I’ve been reading for the past week. Introduction When computer networks (the prelude to the internet) were conceived, it was up to programmers at the time to create an architecture that was reliable and future-proof. Sockets came about as a middle layer between the metal of the machine and software applications. The nice thing about this layer is that it lends to abstracting away details. Abstracting the hardware and software layer means that these layers of independent of one another. That is, software applications are unaffected by hardware architecture and vice versa. In fact, we’ve seen this happen many times already with the transition from dial-up to broadband (and from Netscape to Chrome). The convenience of the abstraction allows programmers to not worry about the underlying hardware. So, what exactly is a socket? And why are they important? This article will aim to give a brief overview. I leave it up to the reader to chase more information about what they find interesting, but this article summarizes what I have learned from multiple sources (cited at the bottom). Sockets Sockets have changed remarkably little since their inception. Conceptually, you can think of them as akin to file buffers! The socket follows the UNIX ideology that everything is a file. The socket allows one to read, write, and send off data to the machine’s hardware. The socket’s API was designed to be expanded to have many, many protocols, but all you need to know about is two socket families and two IP protocols. User-Datagram Protocol (UDP) UDP sockets do not guarantee data delivery. It is a best-effort protocol The best-effort method provides faster sends and requires less information than its counterpart UDP is commonly used for gaming and other applications that can afford packet-loss Transmission Control Protocol (TCP) TCP guarantees that the data is sent to the receiver sequentially and error-free TCP is slower but handles any critical data transmissions where both sides need to be sure that the data has been sent and received This socket type is extremely common Sockets essentially ‘bind’ to an address on your local computer that corresponds to the hardware. There can only be one socket per address reserved, and the operating system tends to reserve ports below 1024. Once bound, you can write and read to and from that address. It’s important to remember that neither TCP nor UDP sockets can guarantee that the data can be sent/read in one cycle. Be conscious of buffer limitations, especially from a C/C++ perspective where keeping track of memory is essential. IP versions complicate sockets Life was once simple, there were IP addresses to go around. We all used IPv4 without a second thought. Unfortunately, these addresses (you’ve seen them, something like 192.168.1.0) need to be unique to be used on the web. We’ve run low. To future proof the web, the big wigs that set standards came out with IPv6 (something like 2001:0db8:0000:0000:0000:8a2e:0370:7334). IPv6 gives many, many more addresses. The two IP addresses don’t mix out of the box. That said IPv6 does provide interoperability. You still need to be wary of making client/server applications that can handle both IP standards. Let’s discuss that now. The Basic Pattern of networking There are two classes of applications on the web. There is the client and the server. A server application waits for a client to connect to an address that the application is bound to. Upon a client connection, the server application will use an additional socket (so that the original can keep watch for new clients), and on the new socket serves the client with data or wait for a command. A client will bind to a socket on its machine, then take an address or name and attempt to connect to the address. Both the server and client applications can send, write, and receive. There is a difference, however. A user controls the client program and typically sends commands to the server. A server runs forever and reacts to given commands. This basic pattern repeats itself on the internet. Anything from Spotify to your bank website follows this pattern. We are going to replicate the pattern here with a simple program. The program will be IP agnostic, with the caveat that we will have to explain quite a few concepts, but the payoff is you can copy this style and get rolling (if traffic isn’t insane). Without further ado: Client code This code example implements a TCP client, composed of four steps: Create a TCP socket using socket() Establish a connection to the server using connect() communicate using send() and recv() close the connection using close() The client takes a server address/ domain name, a string, and, optionally, a port. This example borrows heavily from (Donahoo, Calvert, 2009). includes #include #include #include #include #include #include #include main int main(int argc, char *argv[]) { // we want 4 args the program name and the last 1 is optional if (argc 4){ fputs(\"Parameter(s): [ ]\", stderr); exit(-1); } char *server = argv[1]; // first argument, after the program name, is the server address/name char *echoString = argv[2]; // second arg: string to echo // third argument is optional server/port number char *service = (argc == 4) ? argv[3] : \"echo\"; int sock = setupTcpClientSocket(server, service); if (sock ai_next) { sock = socket(addr-\u003eai_family, addr-\u003eai_socktype, addr-\u003eai_protocol); // try to bind for each addr in linked-list until successful if (sock ai_addr, addr-\u003eai_addrlen) == 0) break; // break out of loop if success close(sock); sock = -1; // finished loop without a success! bad! } freeaddrinfo(servAddr); // remove the linked list from memory since we're finished with it return sock; // our new socket } Server code The code implements a TCP server, composed of four steps: Create a TCP socket using socket() Assign a port number to the socket with bind() Tell the system to allow for connections to the port using listen() Repeat the following: a. Call accept() to get a new socket for each client connection b. communicate with the client with send() and recv c. close the client connection with close() The server takes a port as its argument. The code borrows from (Donahoo, Calvert, 2009). includes #include #include #include #include #include #include #include #include // we will use this to specify the queue of connections to our server static const int MAXCON = 5; main int main(int argc, char *argv[]) { if (argc != 2) { // we want two arguments, the program itself and the port fputs(\"Parameter(s): ai_next) { // loop through all the returned addresses until one works servSock = socket(servAddr-\u003eai_family, servAddr-\u003eai_socktype, servAddr-\u003eai_protocol); // try to bind the socket if (servSock ai_addr, servAddr-\u003eai_addrlen) == 0) \u0026\u0026 (listen(servSock, MAXCON) == 0)) // if bound works and can listen to socket { struct sockaddr_storage localAddr; // sockaddr_storage is IP agnostic socklen_t addrSize = sizeof(localAddr); if (getsockname(servSock, (struct sockaddr *) \u0026localAddr, \u0026addrSize) 0) { ssize_t numBytesSent = send(clntSocket, buffer, numBytesRcvd, 0); if (numBytesSent sa_family) { // need to convert to given address either to ipv4 or ipv6 compatible structure, using sockaddr_in or sockaddr_in6 case AF_INET: numericAddress = \u0026((struct sockaddr_in *) address)-\u003esin_addr; port = ntohs(((struct sockaddr_in *) address)-\u003esin_port); // network to host short break; case AF_INET6: numericAddress = \u0026((struct sockaddr_in6 *) address)-\u003esin6_addr; port = ntohs(((struct sockaddr_in6 *) address)-\u003esin6_port); // network to host short break; default: fputs(\"[unknown type]\", stream); return; } if (inet_ntop(address-\u003esa_family, numericAddress, addrBuffer, sizeof(addrBuffer)) == NULL) // convert ipv4 or ipv6 address (inet) from bytes (network), to printable (string) fputs(\"[invalid address]\", stream); else { fprintf(stream, \"%s\", addrBuffer); // print the address if (port != 0) fprintf(stream, \"%u\", port); // print the port } } Running our example Here is a github link of the files, which we have names client.c and server.c. We need to do the following to make this example run: compile the two programs using a compiler like gcc: gcc client.c -o client \u0026\u0026 gcc server.c -o server run the server first, ./server 5000 (running at port 5000) run the client on a different terminal window at the server address and port, in this example 0.0.0.0 5000, ./client 0.0.0.0 \"echo this\" 5000 You should see this on the server window and this and on the client window Where to go from here? To those interested in learning more about sockets and their rich history in networks, I direct you to the following sources. The first is completely free and a high-level overview in a similar style to this article. The second provides more depth and background and comes from an academic setting. Bib Hall, B. “Beej J. (n.d.). Beej’s Guide to Network Programming: Using Internet Sockets. https://beej.us/guide/bgnet/ Donahoo, M. J., \u0026 Calvert, K. L. (2009). TCP/IP sockets in C: Practical guide for programmers (2nd ed). Morgan Kaufmann. https://www.sciencedirect.com/book/9780123745408/tcp-ip-sockets-in-c ‘Till next time space cowboy – Alex","date":"2021-06-16","permalink":"/blog/sockets-in-c/","summary":"A high-level introduction to sockets, or what I’ve been reading for the past week. Introduction When computer networks (the prelude to the internet) were conceived, it was up to programmers at the time to create an architecture that was reliable and future-proof. Sockets came about as a middle layer between the metal of the machine and software applications. The nice thing about this layer is that it lends to abstracting away details. Abstracting the hardware and software layer means that these layers of independent of one another. That is, software applications are unaffected by hardware architecture and vice versa. In fact, we’ve seen this happen many times already with the transition from dial-up to broadband (and from Netscape to Chrome). The convenience of the abstraction allows programmers to not worry about the underlying hardware. So, what exactly is a socket? And why are they important?","title":"Sockets in C"},{"content":"There has been more and more talk about the fear of rising inflation. That is, a fear of prices increasing because of an increase of the money supply. This topic is fueled by recent decisions from entities like Jerome Powell’s Federal Reserve and their policy of increasing the money supply through buybacks on US Treasuries and “alternative” means. Here, I will pitch my view on modern inflation and why you needn’t fear talks of soaring prices. DISCLAIMER: This article is not an academic piece, it is an opinion piece. Nonetheless, I would not share my opinion if I thought it was valueless. I simply have a undergraduate in economics 1. The money supply is not the primary reason inflation Articles in the media and popular memes have associated the rise of prices with the printing of money. Yet, prices have been rising, but not at the same rate. What does this mean? It is correct that, in several markets, prices have been soaring (particularly housing, construction goods, and automotive). This has little to do with the rise of the money supply (although cheap interests rates may be having a strong impact). On the contrary, these sectors have been experiencing spiraling inflation due to multiple conditions. Real estate has been affected by pre-existing housing shortages, cheap lending, and new COVID-19 driven migratory patterns (Source: WSJ) Construction materials have been affected by the reduced labor supply, the increasing demand from new housing, and COVID-19 “home renovations” (Source: WSJ, WSJ) The car industry is being affected by a shortage of silicon chips needed to power the processors that make up modern vehicles, factory shutdowns, and cheap lending. The reduced supply of new vehicles has made demand spill-over into the used-car market, increasing prices for both markets (Source: WSJ) If inflation were growing due to the money supply, every item in every market would be experiencing comparable price hikes. Yes, inflation is occurring. But for consumers buying consumer goods, the inflation resulting directly from the Federal Reserve’s policy of “printing money” is pennies. 2. Inflation can be a good thing, especially in developed economies The federal reserve has a targeted inflation rate of 2%. Why 2%? There is a meandering economic conversation about why this is a good number— It is supposed to incentivize consumers to spend, while not penalizing borrowers. To summarize, 2% is just an established consensus. That’s right. A bunch of very smart, very influential economists agreed that this was the best target (more accurately, the least harmful target). Does this mean the economy experiences 2% inflation every year? No. not even close. The US economy (and most developed countries) has been experiencing near 0 inflation: a stall of inflation. Inflation has hovered around 0% for most developed countries for about a decade. Reduced inflation is a challenging economic problem because it reduces the incentive to invest or spend money. It also gives governmental organizations less room to maneuver (i.e., interest rates, swap rates), and it means that there has not been enough demand for goods to raise prices. There is a great many case study about Japan’s near 40-year bout with near-0 inflation (I will not link any here. It is a fascinating topic to research) (Source: macrotrends). The frightening economic story is when there is deflation. The classic deflationary event was the Great Depression. Imagine being paid 3 to 10 percent of your money’s value every year to hide it in your mattress. Sounds great? Yes. Ok, but when everyone is being paid to do the same, it is terrible because no one will want to spend money (Those with money will effectively have more money doing nothing)! Being paid to hide your money is a deflationary economic environment. As prices go down, the value of money increases. Again, the result is consumers will want to save more, consuming less, lenders lend less, and investors invest less. We NEED a slightly inflationary environment to keep the economic engine going. 3. Long awaited good news: wage growth My final point is that, after a decade of no real wage growth for Americans, we are finally beginning to see wages outpace the inflation rate for the first time since the 2000s! Wage growth is fantastic news. I must caution that I have not seen any proof that the Fed’s policies are causing the increase of wages. I mention it because the point of this article is to alleviate cries of “Inflation bad! Economy bad!” As wages grow, consumers will have more money in their pockets. More money means that there is more room to spend and fuel the economy! Conclusion After reading this opinion article, you should come away knowing that anyone who tells you to fear the current inflationary environment is just trying to drive panic or clicks. The current inflationary environment is good for the economy, not threatening. The shocks occurring now in particular sectors (housing) are NOT entirely because of the Federal Reserve’s policies! They are a result of too many buyers in markets with not enough products! I will leave you with this. 1980’s America had an inflation rate of above 10%! Today we have an average inflation rate of under 2% (Source:FRED). – Alex","date":"2021-05-23","permalink":"/blog/the-inflation-question/","summary":"There has been more and more talk about the fear of rising inflation. That is, a fear of prices increasing because of an increase of the money supply. This topic is fueled by recent decisions from entities like Jerome Powell’s Federal Reserve and their policy of increasing the money supply through buybacks on US Treasuries and “alternative” means. Here, I will pitch my view on modern inflation and why you needn’t fear talks of soaring prices.","title":"The Inflation Question"},{"content":"Takeaways Finished the KBAI and HCI courses offered by GA TECH with A’s! takeaways Completed Head First C by David Griffiths Had the first session of my new D\u0026D campaign latex Courses and life takeaways I posted my thoughts and review for Knowledge-Based AI and Human-Computer Interaction offered by Georgia’s Institute of Technology last week. This week I received final grades. I was cheered to see that I scored As in both classes. I don’t like to give myself much fanfare for accomplishments, but here I want to say with solid emphasis that I’m excited to start the program with a 4.0. In the previous articles, I discussed the courses themselves. Now, I would like to quickly discuss what going back to school for my post-graduate while working has taught me. Deadlines defeat procrastination There’s an odd paradox with work I have come to realize. The bigger a project and the higher its importance, the more likely you are to want to procrastinate. The deadlines set by the course leave you with few opportunities to lose momentum or for free time. Applying this scheduling to my everyday life has made me more time-sensitive and aware. I don’t like giving away my time for anything now except study, work, and chosen leisure. Research, structure, and LaTeX In undergrad, I read research papers. Maybe 2 or 3 a semester. Post-grad turned this up to an 11. Human-computer interaction alone made me read 2-3 academic articles a week (average of 15 pages each). The experience made me appreciate the importance of structuring information. All work must be as accessible to your reader (target audience) as possible. There is a reality that should be kept when writing any piece. That is, your work is not the essence of any reader: vital information must be communicated effectively. Both courses used the Joyner David Format (JDF— Yes, the professor’s name). These courses finally gave me an excuse to focus on learning LaTeX. LaTeX is a tool that outputs PDF documents. The PDFs it produces are simply lovely. It’s a little snobby to say, I admit, but the fonts provided look so… clear. When LaTeX does work, it is the niftiest tool! No dragging things or praying to get formatting correct (Looking at you Microsoft Word!). Just set it and forget it. I still can’t really recommend it to people over tools like Microsoft Word and markdown because the cost of learning it (and the frustration!) is not worth it. Schedule This last point circles back to the first. I took a holiday early in the semester and, I loved it. But I did not realize the cost of taking a holiday mid-semester until a week or two later. Vacations mess with your rhythm, so after I finished my trip, I found my timings were all over the place. The sporadic schedule stayed that way for the rest of the semester. I paid an unexpected price in Monster energy drinks and stress. Set your schedule sooner rather than later. Head first C I worked in C in the past but had to switch back to Python and Java for work + school. I picked up Operating Systems for the upcoming fall semester. The course is heavy in C, so I have been taking this time to prepare. After a few exercism.io exercises, I realized I needed to hit the books again. I can still recommend Beej’s Guide to C Programming, to a beginner. Beej has a few too many anecdotes when you want to get to the material. Cue the O’Reilly’s Head First C. I finished Head First C in about two weeks. It covered everything. Memory. Networking. System calls. Parallel processing. Fantastic read. It was laden with information that was entertaining and informative. Dungeons and Dragons Saturday, I hosted a session of Dungeon \u0026 Dragons I had been planning for a few weeks. The story’s set in a fantasy book I have been reading. If you have never played D\u0026D, it is a structured improvisation with combat and other systems. The first session was a lot of fun. I won’t discuss the details here, but I will mention that I enjoyed hearing my group of players assault me with questions about the game like, “what happened! Who is this? Are they connected?” Upcoming Goals C practice + LeetCode Update the resume to LaTeX Upcoming D\u0026D session Reviewing linear Algebra with classmates -Well, till next time space cowboy Alex","date":"2021-05-13","permalink":"/blog/weekly-check-in/","summary":"Takeaways Finished the KBAI and HCI courses offered by GA TECH with A’s! takeaways Completed Head First C by David Griffiths Had the first session of my new D\u0026D campaign latex Courses and life takeaways I posted my thoughts and review for Knowledge-Based AI and Human-Computer Interaction offered by Georgia’s Institute of Technology last week. This week I received final grades. I was cheered to see that I scored As in both classes. I don’t like to give myself much fanfare for accomplishments, but here I want to say with solid emphasis that I’m excited to start the program with a 4.0.","title":"Weekly Check-in"},{"content":"Takeaways The course covers classic AI algorithms like generate and test and case-based learning A fantastic introduction to the program, the coursework is lighter on programming than others. There is a lot of writing, with weekly deliverables What is Knowledge-based AI (KBAI)? Knowledge-based AI (KBAI) is a course offered by GATECH’s OMSCS. The course deals with applying human-like cognitive techniques to develop artificial intelligence. The class provides two goals: Understand the basic architectures, representations, and techniques for building knowledge-based AI agents issues and methods of knowledge-based AI KBAI is a fantastic introduction to the program. The class uses Python exclusively. You can succeed in the course with little to no background in computer science algorithms and mathematics (You will have to work harder!). The class shines when connecting AI techniques to human cognition. The lectures introduce theories from KBAI literature, postulating on how humans learn, what creativity is, and what humor is. In a way, the class is subtly both a computer science course and a course on human psychology. What did I learn? Common strategies in KBAI Utilizing semantic networks for problem solving Methods like generate and test, means-ends analysis, Incremental concept learning, and case-based reasoning Data structures like frames, discrimination trees, and indexing Learning about learning The course stresses how to set up an AI agent to learn and how that relates to human psychology AI image perception The course project is solving RPM tests (image) using an AI agent. You are given images to work with so will have to learn to use an image processing library like Pillow or OpenCV Linear algebra application Linear algebra was not required, but it helped when thinking about how to process images as images are represented as matrices using Python’s NumPy What did we do? Mini projects Starting simple doing the sheep and wolves problem Later more difficult, processing language to create meaning by giving your agent an ontology of the world Explored ethics and laws concerning AI Raven’s Progressive matrices Why take this course? Good introduction to the program The professor is a fantastic lecturer Good, hands-on review into algorithms, especially tree traversals and search algorithms You get to design your own AI program! -Well, till next time space cowboy Alex","date":"2021-05-08","permalink":"/blog/kbai-review/","summary":"Takeaways The course covers classic AI algorithms like generate and test and case-based learning A fantastic introduction to the program, the coursework is lighter on programming than others. There is a lot of writing, with weekly deliverables What is Knowledge-based AI (KBAI)? Knowledge-based AI (KBAI) is a course offered by GATECH’s OMSCS. The course deals with applying human-like cognitive techniques to develop artificial intelligence. The class provides two goals: Understand the basic architectures, representations, and techniques for building knowledge-based AI agents issues and methods of knowledge-based AI","title":"Knowledge-Based AI Review (CS7637)"},{"content":"Takeaways Human computer interaction (HCI) is a course offered by GA Tech’s OMSCS Taking the course will equip you with design principles and techniques established in the field of HCI What is HCI? The past decade has revealed a trend of embedding microprocessors in non-traditional applications. For example, a CPU in a refrigerator would be unheard of only a decade ago. The growing ubiquity of processing power has fueled the growth of the field of Human-computer interaction. The course is valuable in exposing students to HCI and teaching them to adopt the principles and methods developed over the last century. The curriculum presents traditional computer interfaces (e.g., computers and smartphones) and non-traditional interfaces, such as human-computer interaction in education, VR, augmented reality, and wearables. The course moves on to teach how humans interact with computers and some common design pitfalls. If the class had a theme, perhaps it would be, “Designers should not design for designers, designers should design for the users.” and, “You are NOT your user.” The course stresses involving users to generate feedback in each step of the design process. It presents a methodology for the application of user-centered design both in research and in industry. What did I learn in HCI? The design lifecycle The course emphasizes that the user should be involved in each step of the design lifecycle. The lifecycle consists of a non-linear model: needfinding, design alternatives, prototyping, evaluation Each phase involves the user either directly or given by incorporating previous user feedback. For example, needfinding is done by identifying a user type, recruiting participants of that user type, then gathering data via interview, survey, think-aloud, etc. You are not your user, and other principles of HCI Principles of design are taught in the course, with the caveat that they cannot replace a user-centered approach. Nonetheless, the principles prove useful both for analyzing and coming up with interfaces. The principles discussed are those established by giants in the field such as Don Norman’s discussion of discoverability (i.e., an interface should allow users to discover how to use it without fear of error) and the Feedback Gulfs. User-centered design and Agile development This portion of the course focused on adapting the user-centered design model to modern, quick-turnaround industries by adapting the lifecycle to Agile sprints. The literature in HCI backs this up with authors like Stephanie Chamberlain, Helen Sharp, and Neil Maiden making a case for an Agile, User-centered design hybrid. The result is a user-centered product with a “caffeinated” design lifecycle that can thrive in time-sensitive projects familiar to the software industry. What type of work to expect from HCI (6750)? Plenty of writing assignments “M” assignments propagating students through the design lifecycle Final project involves solo investigation using the design lifecycle model (20-page paper) Exploration of the literature in the field Designing and executing needfinding, prototyping, and evaluation Why take this course? You’re intrested in solid design principles from an academic perspective You realize and embrace that software is an interdisciplinary field You want a “soft” entrance to your master’s program focused on writing and not programming. Great to develop soft skills like communication -Well, till next time space cowboy Alex","date":"2021-05-05","permalink":"/blog/hci-review/","summary":"Takeaways Human computer interaction (HCI) is a course offered by GA Tech’s OMSCS Taking the course will equip you with design principles and techniques established in the field of HCI What is HCI? The past decade has revealed a trend of embedding microprocessors in non-traditional applications. For example, a CPU in a refrigerator would be unheard of only a decade ago. The growing ubiquity of processing power has fueled the growth of the field of Human-computer interaction.","title":"Human-Computer Interaction (CS6750)"},{"content":"Takeaways My initial experience as an entrant in the Online Master’s in Computer Science (OMSCS) offered by the Georgia Institute of Technology (GA TECH) The program is tough: expect 20 hours per course. For my first semester, I fully immersed myself in academic literature, project documentation, and analysis Introduction A shipwreck of fear. An incredible sense of hopefulness. I completed my first semester at the Georgia Institute of Technology as a candidate for the Master’s program in Computer Science. I grew up somewhere where statistically, I did not have much of a chance of escaping poverty. Few friends from high school attended or completed college. I was the first and only one in my family to achieve a bachelor’s. My father started working as a pre-teen in Mexico to support his family. The only man in a family of six sisters. My mother only years later received a GED. I am considerably thankful but have also been self-absorbed in some level of doubt. Who do I look to for advice? Was I even supposed to get this far? Maybe you feel this way too. Here I will discuss the program itself, my initial impressions, and how I have grown since the beginning of the semester. The Program The Online M.S. CS (OMSCS) program offered by Ga Tech is unique in it extends the academic quality of an Ivy school to the public university system. The winning aspect for me was the practice of accessibility of education as a principal and the resources of notable professors in each field. Various institutions try to sell students a message of leadership and impact on the world. I believe OMSCS is one of the few programs that is practicing what they preach. The diversity of the program is incredible. One semester in, and already I have had the chance to network with some incredible members of my cohort, far removed from my home state of Georgia. The bridging of education with technology is what excited me when I joined the program My initial impressions It is an astonishing program. Allow me to state my bias now— I wanted to go to Ga Tech as my graduate school since setting my eyes on computer science. I was fortunate to meet a Ga Tech student interning with my team when I worked as a data analyst. He helped influence me. He told me about the school and what he learned. I needed to find a program that challenged me like that. Thanks to encouragement from my mentors, I tried applying. Without a formal computer science background, I was rejected. Devastated, I tried again. I earned additional Computer Science credits and worked to merit letters of recommendation from my professors and managers. This time I received a letter congratulating my acceptance into the program. However, there is a stipulation. Students must maintain a 3.0 GPA their first year or be automatically dropped from the program. In other words, you enter the program under academic prohibition. While initial registration and application were hectic, especially coinciding with covid, the school did not disappoint. Although the material and discussion are entirely online, I feel like I have made as many connections as I did in undergrad with double the course load. The courses go straight to the meat and potatoes of the subject they promise to teach. Typically, there is an assumption that a master’s program is more lenient than undergraduate programs. After all, schools are competing for YOU, not the other way around (have you heard any MBA radio ads lately?). Not the case here. To summarize the program so far: stimulating and demanding. Growth I will be frank. I am a terrible writer. I wanted to get a lenient introduction to the program, so I selected some classes heavier in writing than programming to test the waters. I ended up registering for human-computer interaction and Knowledge-based AI, both taught by Professor David Joyner. Each class demanded an average of 20 hours of work every week. Reading academic literature, writing analysis, and solving problems using AI concepts ate away at any possibility of free time from my life. The biggest thing I can tell you is that my writing has improved significantly. My wife teases me all the time, “Your writing is so much better!” I have always been insecure about the way I write. It fills me with happiness. I could only achieve this because week after week, I wrote pages and pages of analysis. On top of this, I got familiar with Georgia tech standards when it comes to programming. The lectures hinted at high-level concepts to solve problems we were assigned (in the form of mini-project and AI programs), but the environment is sink or swim. The lectures and course materials only presented high-level thinking and general algorithms but no explicit code snippets. KBAI was particularly striking because the semester-long project was an AI agent capable of perceiving images for deliberation. In summary, I was nose-deep in reading documentation from libraries like OpenCV. I will write reviews for both courses, both here and on OMSCentral. My next semester will be this fall. I am planning on taking an operating systems class. -Well, till next time space cowboy Alex","date":"2021-04-29","permalink":"/blog/initial-thoughts-on-the-omscs/","summary":"Takeaways My initial experience as an entrant in the Online Master’s in Computer Science (OMSCS) offered by the Georgia Institute of Technology (GA TECH) The program is tough: expect 20 hours per course. For my first semester, I fully immersed myself in academic literature, project documentation, and analysis Introduction A shipwreck of fear. An incredible sense of hopefulness. I completed my first semester at the Georgia Institute of Technology as a candidate for the Master’s program in Computer Science. I grew up somewhere where statistically, I did not have much of a chance of escaping poverty. Few friends from high school attended or completed college. I was the first and only one in my family to achieve a bachelor’s. My father started working as a pre-teen in Mexico to support his family. The only man in a family of six sisters. My mother only years later received a GED. I am considerably thankful but have also been self-absorbed in some level of doubt. Who do I look to for advice? Was I even supposed to get this far? Maybe you feel this way too.","title":"Initial Thoughts on the OMSCS"},{"content":"TL;DR: Spring Semester 2021 begins Jan 14th An overview of the registration process has been like An assessment of how prepared I feel after the last few months of studying What I hope to get out this Semester I won’t be able to commit to any sort of regular schedule on the site. I would like to do some sort of update post-midterms and post-finals. Thank you for your understanding. Spring Semester 2021 I am extremely excited (and extremely nervous) about beginning the OMSCS (Online Master of Computer Science) program at Georgia Institute of Technology. My feelings boil down to a concentrated mix of excitement, nervousness, and a heavy hand of imposter syndrome. My imposter syndrome feeling is further amplified by the way the program’s first year works: you are on academic probation until you finish two foundation courses with a GPA average of 3.0 or better (academic hunger games anyone?). I’ve done a lot to try and prepare for this moment. I’ve prepped my schedule and studied to compensate for my weakest points (mathematics). I’ve picked up C/ C++ in order to avoid having to learn both the course material and the programming language simultaneously. Registration This went down more or less the way I expected it to: It was a mess. We were told, emphasized, that by 18:00 GMT -5, we’d be given a time ticket to register. 18:00 came and went. Some two hours later (and a few http errors) the system resolved itself and I was given a time ticket for 10:30 AM, the next day. I set two alarms and scheduled the time on my calendar. Gave myself a 30-minute head start, and I was devastated to find my ideal class full. The wait list was at ~800. Both Machine Learning for Trading and Software Development Process were full to the brink. I made my backup selection of classes, a little disappointed. Quickly enrolling into Knowledge Based AI and Computational Photography. I wait listed a few other courses, but this was futile. GATech informed me that there is a policy of having a max of 6 credit hours without an approved waiver. In other words, I would either accept my schedule as is (reviews told me to expect a combined 30-hour commitment per week) or drop my schedule in favor of wait listing a class. I went with the latter, as I am just not confident enough to risk committing to two “medium” courses. I planned instead to have one “medium” course and one “easy” course according to reviews. As of writing I am still registered for Knowledge based AI (KBAI) and on the wait list for Human Computer Interaction (The queue is shorter for HCI than for ML4T or SDP). Overall, I am content with the way the Registration process played out. Personal Assessment of my Readiness for the Program Oh, let’s be truthful. I am more excited than I am nervous, but I still do feel nervous. I studied for the last 6 months focused on readying myself for the academic rigor offered by GaTech. My first 3 months were spent focused solely on programming languages and CS topics while the most recent 3 months were solely spent on hardening my math background. Those first three months were mostly spent picking up Java and C/ C++. This included reading Bjarne’s book, JetBrains Academy, and exercism.io. I also familiarized myself with common software designs such MVC, factory methods, and singleton classes. I started 2020 focused on developing in Java. Once I finished my android app, I pushed myself into the C language world. After a few trivial projects I moved on to C++ just to be able to utilize their standard library. I started the application process for grad school at around this point and realized I urgently needed to improve my mathematics background. Ideally, I thought starting from SAT level and building up to calculus and linear Algebra would work best. As time started running out, I decided to dive into Linear Algebra. I finished a textbook on the subject + the practice exercises and moved on to discrete mathematics. I was able to confidently finish around 70% of that material while also working on calculus I-III. Overall, I think I did as best I could with the time constraints. I know for a fact my math is a lot more solid than it was a year ago and have kind of began to (shaves some parmesan) appreciate the beauty of mathematics. What I hope to Get Out of Semester More than anything I hope to get confidence out of the semester. I am diving sort of the deep end of the pull with 6 credit hours, but I had to do so to qualify for financial aid. From the courses themselves, I hope to learn to make rudimentary AI in KBAI hopefully serving as a soft introduction to the program. I have read that the course is more writing than programming heavy, and what programming that is assigned is in Java or Python (both languages I am comfortable writing in). From HCI, I hope to really adopt a user-oriented mindset when writing programs. I think this class is very valuable to have early in the program (and early into my career) because this is a topic that is usually overlooked by many developers. I will be letting you know with time my thought on the courses and my struggles and success. ‘Till next time Space Cowboys","date":"2021-01-10","permalink":"/blog/starting-omscs-at-gatech/","summary":"TL;DR: Spring Semester 2021 begins Jan 14th An overview of the registration process has been like An assessment of how prepared I feel after the last few months of studying What I hope to get out this Semester I won’t be able to commit to any sort of regular schedule on the site. I would like to do some sort of update post-midterms and post-finals. Thank you for your understanding.","title":"Starting OMSCS at GaTech"},{"content":"An update from the last time we spoke. I want to get some in depth articles up, but I’ve only been putting time into mathematics in preparation for more theory based courses I am expecting this upcoming semester. Working on I was able to finish Hefferon’s Linear Algebra. I am now working on the labs provided in the book. On my efforts in cpp: Completed Udacity’s free C++ for Programmers About a fifth through Bjarne’s excellent book Programming Principles and Practice Using C++ finished up Hackerrank’s relevant cpp exercises and obtained the gold badge. Exercism.io Found an excellent and noteworthy site thanks to reddit. It’s called Advance Projects for Beginners and currently working on the life project. Started diving into Al Doer and Ken Levasseur’s Applied Discrete Structures but Dropped it in favor of Lehman’s Mathematics for Computer Science along side MIT Opencourseware’s Mathematics for Computer Science I found these sources too convoluted. Instead, I switched to a recently published THIN and excellent introduction by Harry Lewis and Rachel Zax on the subject. Hitting 60 wpm consistently since my last post. Touch typing is proving to be fruitful. For resources check out: Typing Club keybr Goals for the Upcoming Week Aiming to finish Hefferon’s Lab modules by mid-December. Hit 80-90 WPM using touch typing. A medium sized C++ program on my git. finish exercism’s C++ course. Finish intro level Discrete Mathematics textbook (and exercises) by the New Year. Reflections Since last Post It has been a month since I’ve really done the morning routine bit. That is, waking up at ~04:30. I found the hump was the first two weeks, but it has been rewarding. I get at least 4-6 hours of studying in every day because of it. I feel a little regret for not getting a regular post in these past few weeks, but I think it’ll be this way until I gather enough confidence in the upcoming school year, unfortunately. There was a covid scare recently at my workplace. There was a lot of anxiety and a reminder that this virus is unpredictable and ever-present. We are planning a weekend trip but have been finding it difficult to book. We were still lucky enough to check out some of the museums near us… There’s so much frustration learning that you know very little. It’s never ending, but I think it’s ok. and I enjoy it at the same time. I’m rambling now. -Well, till next time space cowboy Alex","date":"2020-11-02","permalink":"/blog/weekly-check-in-11-02-20/","summary":"An update from the last time we spoke. I want to get some in depth articles up, but I’ve only been putting time into mathematics in preparation for more theory based courses I am expecting this upcoming semester. Working on I was able to finish Hefferon’s Linear Algebra. I am now working on the labs provided in the book. On my efforts in cpp: Completed Udacity’s free C++ for Programmers About a fifth through Bjarne’s excellent book Programming Principles and Practice Using C++ finished up Hackerrank’s relevant cpp exercises and obtained the gold badge. Exercism.io Found an excellent and noteworthy site thanks to reddit. It’s called Advance Projects for Beginners and currently working on the life project. Started diving into Al Doer and Ken Levasseur’s Applied Discrete Structures but Dropped it in favor of Lehman’s Mathematics for Computer Science along side MIT Opencourseware’s Mathematics for Computer Science I found these sources too convoluted. Instead, I switched to a recently published THIN and excellent introduction by Harry Lewis and Rachel Zax on the subject. Hitting 60 wpm consistently since my last post. Touch typing is proving to be fruitful. For resources check out: Typing Club keybr Goals for the Upcoming Week Aiming to finish Hefferon’s Lab modules by mid-December. Hit 80-90 WPM using touch typing. A medium sized C++ program on my git. finish exercism’s C++ course. Finish intro level Discrete Mathematics textbook (and exercises) by the New Year. Reflections Since last Post It has been a month since I’ve really done the morning routine bit. That is, waking up at ~04:30. I found the hump was the first two weeks, but it has been rewarding. I get at least 4-6 hours of studying in every day because of it.","title":"Weekly Check-In 11-02-2020"},{"content":"An update from the last time we spoke. I want to get some in depth articles up, but I’ve only been putting time into mathematics in preparation for more theory based courses I am expecting this upcoming semester. Working on Linear algebra is still taking up most of my day. Hefferon’s Linear Algebra is still serving me well. What’s more is I discovered his recently uploaded lectures that follow the textbook. A blessing of the lockdown Switched my efforts from C to C++ just because of the STD. The syntax is a little boggling compared to Java. I am Using: Udacity’s free C++ for Programmers Bjarne’s excellent book Programming Principles and Practice Using C++ Hackerrank + Exercism.io Speaking of exercism.io, I’ve started mentoring on their Java track. Started diving into Al Doer and Ken Levasseur’s Applied Discrete Structures but Dropped it in favor of Lehman’s Mathematics for Computer Science along side MIT Opencourseware’s Mathematics for Computer Science Bought a Ducky One mini with Silent Cherry Red’s to replace my blue’s. (basically was too loud at sensitive times. I wanted too keep typing at 5am without waking my SO). Alongside that last point, I am converting to touch typing currently hitting around 30 WPM which is terrible, but I will keep it up and see how it does. If you’re interested I am using: Typing Club keybr Goals for the Upcoming Week Aiming to finish Hefferon’s textbook early the middle November. Hit 80-90 WPM using touch typing. A medium sized C++ program on my git. finish exercism’s C++ course. Reflections Since last Post I was able to limit my caffeine and have been regularly hitting the 6-8 hour range studying. I did it by keeping a strict schedule, up by 4:30AM and in the Linear algebra a cup of coffee later (around 5am). Let’s figure out on avoiding burn out now. Naps have really helped. -Well, till next time space cowboy Alex","date":"2020-10-19","permalink":"/blog/weekly-check-in-10-19-20/","summary":"An update from the last time we spoke. I want to get some in depth articles up, but I’ve only been putting time into mathematics in preparation for more theory based courses I am expecting this upcoming semester. Working on Linear algebra is still taking up most of my day. Hefferon’s Linear Algebra is still serving me well. What’s more is I discovered his recently uploaded lectures that follow the textbook. A blessing of the lockdown Switched my efforts from C to C++ just because of the STD. The syntax is a little boggling compared to Java. I am Using: Udacity’s free C++ for Programmers Bjarne’s excellent book Programming Principles and Practice Using C++ Hackerrank + Exercism.io Speaking of exercism.io, I’ve started mentoring on their Java track. Started diving into Al Doer and Ken Levasseur’s Applied Discrete Structures but Dropped it in favor of Lehman’s Mathematics for Computer Science along side MIT Opencourseware’s Mathematics for Computer Science Bought a Ducky One mini with Silent Cherry Red’s to replace my blue’s. (basically was too loud at sensitive times. I wanted too keep typing at 5am without waking my SO). Alongside that last point, I am converting to touch typing currently hitting around 30 WPM which is terrible, but I will keep it up and see how it does. If you’re interested I am using: Typing Club keybr Goals for the Upcoming Week Aiming to finish Hefferon’s textbook early the middle November. Hit 80-90 WPM using touch typing. A medium sized C++ program on my git. finish exercism’s C++ course. Reflections Since last Post I was able to limit my caffeine and have been regularly hitting the 6-8 hour range studying. I did it by keeping a strict schedule, up by 4:30AM and in the Linear algebra a cup of coffee later (around 5am). Let’s figure out on avoiding burn out now. Naps have really helped.","title":"Weekly Check-In 10-19-2020"},{"content":"A quick post to the site to let people know I am alive for the week of 9/21/2020 to 9/27. I hope to get an article out sometime in October on my current project involving oAuth1 \u0026oAuth2. Since I’ve gotten accepted into GA Tech I’ve been brushing up on my math and C / C++. Working on Linear algebra. Currently neck deep in Hefferon’s excellent and free Linear Algebra Lots of low-level C programming. Never realized how much higher-level languages took care of string manipulation for you. Hacker rank has been an excellent tool for practice. Besides that, I have been giving exercism.io a try. Built a CLI hangman game in C with 1000+ word bank. Finished Unix Workbench course on Coursera. Focused on command line stuff and Bash. Android phone screen gave out on me (from flicker to dead). Have switched to iPhone. On that note I’ve had to change my time management application from my android based app to a Linux based CLI Watson. Has been pretty clean so far. Goals for the upcoming week Trying to limit my caffeine to a healthy amount from the copious amounts I have been drinking. I am doing 1 cup a day. Aiming to get 8+ hours a day studying. Switching between C/ C++ Still working on using only VIM or VIM style interfaces. Checkpoint my Linear algebra to prepare for the first midterm. etc. Excited about my special someone. Trying to get them a gift that won’t suck. Have been using a vertical second monitor at my dock. Been getting some power issues. Not enjoying iOS, but it’s workable. – till next time. 😊","date":"2020-09-27","permalink":"/blog/weekly-check-in-9-27-2020/","summary":"A quick post to the site to let people know I am alive for the week of 9/21/2020 to 9/27. I hope to get an article out sometime in October on my current project involving oAuth1 \u0026oAuth2. Since I’ve gotten accepted into GA Tech I’ve been brushing up on my math and C / C++. Working on Linear algebra. Currently neck deep in Hefferon’s excellent and free Linear Algebra Lots of low-level C programming. Never realized how much higher-level languages took care of string manipulation for you. Hacker rank has been an excellent tool for practice. Besides that, I have been giving exercism.io a try. Built a CLI hangman game in C with 1000+ word bank. Finished Unix Workbench course on Coursera. Focused on command line stuff and Bash. Android phone screen gave out on me (from flicker to dead). Have switched to iPhone. On that note I’ve had to change my time management application from my android based app to a Linux based CLI Watson. Has been pretty clean so far. Goals for the upcoming week Trying to limit my caffeine to a healthy amount from the copious amounts I have been drinking. I am doing 1 cup a day. Aiming to get 8+ hours a day studying. Switching between C/ C++ Still working on using only VIM or VIM style interfaces. Checkpoint my Linear algebra to prepare for the first midterm. etc. Excited about my special someone. Trying to get them a gift that won’t suck. Have been using a vertical second monitor at my dock. Been getting some power issues. Not enjoying iOS, but it’s workable.","title":"Weekly Check-In 9-27-2020"},{"content":"C is one of the oldest programming languages still in use today. It’s attributed success comes from its “simplicity.” Weird to hear that when the likes of Python exisits. But it’s true, C for its time was one of the easier, and more robust languages available for developers. This grandpappy of language originates from 1972. It picked up steam from IBM’s decision to support it on its PC line of consumer computers. Then K \u0026 R (Brian Kernighan and Dennis Ritchie) published what came to be known as the “C Bible”, The C Programming Language in 1978. This book was so influential that it became the pseudo standard of the language. Sounds great and dandy, right? Well here we come to… The Difficulties of C barriers of C is an alternative title. This language is so old and so influential. It’s had nearly 50 years to develop, build a community, improve access, and so on. Yet, it is so difficult as a beginner to find the resources for learning this language. And this is coming from a guy who has been in the programming world for a while. I thought, “Java is no big deal, neither is Python so C should be OK.” Those languages do not prepare you for the novelty of handling memory in C. So, who do I turn to? Why Google! Reading Materials After some Google Fu I am recommended K. N. King’s A Modern Approach. I get a copy of the PDF (There’s no E-book format available) and load it onto my Kindle. I remember coming in King references K \u0026 R’s 1988 book. The it dawns on me. C has a scarcity problem of material to learn from. It’s the opposite of a language like JavaScript or Python where there’s people on every corner of YouTube peddling their material for you to buy. What I am saying is that C only has a handful of “eh” to good quality material to learn from. The Takeaway I’ve documented the materials I dedicated to before moving on below. If you’re looking to learn C (it really is a simple language, even if a little inaccessible) just skip my dancing around and jump to Beej’s guide. His stuff is funny, simple, and in depth enough to understand what’s really going on. If you want it in E-Book format, save the html page and plug it into a “html to mobi” converters online. Beginning Programming with C For Dummies Dan Gookin 2013 6/10 leaves you wondering. Sometimes fails to explain the why. C Programming: A Modern Approach 2008 K. N. King 5/10 old-school textbook feel Beej’s Guide to C Programming 2007 2007 Brian “Beej” Hall 10/10","date":"2020-09-12","permalink":"/blog/2020-c-programming-barriers-to-entry/","summary":"C is one of the oldest programming languages still in use today. It’s attributed success comes from its “simplicity.” Weird to hear that when the likes of Python exisits. But it’s true, C for its time was one of the easier, and more robust languages available for developers. This grandpappy of language originates from 1972. It picked up steam from IBM’s decision to support it on its PC line of consumer computers.","title":"C Programming Barriers to Entry"},{"content":"Jekyll is a great tool if you want the simplicity of a static website but with more complicated functionality. It offers a load of plugins and maintenance saving methods. The primary advantages are: templating variables and loop functionality support for GitHub pages (a free webhosting platform for anyone with a GitHub account) plugins, database free solutions, and niche cases If this is tempting strap in and I’ll describe my weekend setting up Jekyll. Set up You will want to give the Jekyll [quick setup] (https://jekyllrb.com/docs/) page a look (For this tutorial do only steps 1 \u0026 2). Very friendly if you are on Linux or Mac, not so much on Windows. Windows Lucky for you, I am on Windows which means we’re on Linux. Head over to the WSL2 (Windows Subsystem for Linux- what a time to be alive) page and set it up. grab a Linux distro from the Microsoft store (Ubuntu) and run these commands: launch WSL from command prompt wsl run update (sudo is like as adminastrator in windows) sudo apt update \u0026\u0026 sudo apt upgrade -y clean system sudo apt-get autoremove install Ruby sudo apt-get ruby-full install GCC and Make sudo apt install build-essential follow quick start from Jekyll (Steps 1 \u0026 2) Nice, now we windows users are caught up to the Max and Linux. Choosing a theme This is the fun part of the project. Jekyll has been around for a decent amount of time and the community is mature enough to be both helpful and provide loads of materials. Do a google search for Jekyll themes and you will find a ton. For this tutorial we will use https://jekyllthemes.io/ Now that you have found a theme you fancy click on the “Theme Name on GitHub” button on the right-hand side of the page. If you have never used GitHub before don’t be intimidated, it is at its core a file hosting site for developers. Figuring out Git Ok I take it back; this next part may be a little intimidating. Open your terminal (if you are on Windows, open CMD and type WSL) and type the following git command: git --version If you are greeted with a version number, you are good to go. Otherwise give this article a read. Use Linux / Mac instructions. Pick a folder where you’d like to work on your computer and copy the address. You can navigate to it using the cd (Change Directory) command. If you would like to follow my setup do the following: **You are going to want this in a Linux/ Mac location go to home directory cd ~ create projects folder mkdir projects create web folder inside projects cd projects mkdir Web you should see Web after running the above. ls command just lists files ls Now you will clone the theme you selected from GitHub in the folder of your choosing. To do this, go back to the theme’s GitHub page and find CODE button and copy the link that appears when it is clicked. make sure your terminal is at the right location (see the prompt’s address). and use the git clone command git clone [URL] Typing the ls command should show a new folder with that projects default name. We wont worry about changing the folder name for now. Let’s give our new site a test run. Running Jekyll Start by changing directory into our theme folder cd theme-folder-name update and install jekyll plugins bundle update bundle install launch a local web server to see your site in action (only available to you) bundle exec jekyll serve go to your web browser and go to http://127.0.0.1:4000/ To stop the local server CTRL + C in your terminal Balmy! Could not locate Gemfile Most themes have a Ruby configure file already, but if you run into this issue simply create one. We will do this through the terminal, but a note editor works the same if you save it in the folder as Gemfile create the file nano Gemfile paste the following configurations # Hello! This is where you manage which Jekyll version is used to run. # When you want to use a different version, change it below, save the # file and run `bundle install`. Run Jekyll with `bundle exec`, like so: # # bundle exec jekyll serve # # This will help ensure the proper Jekyll version is running. # Happy Jekylling! gem \"jekyll\", \"~\u003e 4.1.1\" # This is the default theme for new Jekyll sites. You may change this to anything you like. gem \"minima\", \"~\u003e 2.5\" # If you want to use GitHub Pages, remove the \"gem \"jekyll\"\" above and # uncomment the line below. To upgrade, run `bundle update github-pages`. # gem \"github-pages\", group: :jekyll_plugins # If you have any plugins, put them here! group :jekyll_plugins do gem \"jekyll-feed\", \"~\u003e 0.12\" end # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem # and associated library. platforms :mingw , :x64_mingw , :mswin , :jruby do gem \"tzinfo\" , \"~\u0026gt; 1.2\" gem \"tzinfo-data\" end # Performance-booster for watching directories on Windows gem \"wdm\" , \"~\u0026gt; 0.1.1\" , :platforms = \u0026gt; [ :mingw , :x64_mingw , :mswin ] save the Gemfile CTRL+x Y enter Nice. Now jump back up and run both the bundle commands. Publishing your site funky site you got there. Unfortunately, if you try and type in http://127.0.0.1:4000/ on your cell phone with your Wi-Fi off you’ll get nothing. In the past this is the part where you’d have to shell out for a domain name, a webserver, and set up some sort of https service. Luckily, GitHub will circumvent the past. GitHub Pages GitHub pages is a free service that allows you to host sites for free, but with certain limitations. Because our page is effectively a static site we won’t have to worry about those limitations, but we will need to alter our template before we can get it up and running. You could edit your site to match your information, but I found it less troublesome to get the site on GitHub pages first and then make your changes incrementally in case things go awry. Creating the Repository login to GitHub make a new repository by clicking New Name it what you’d like your site to be called (NOT the theme name) confirm with the Create repository button Configuring to GitHub’s liking We need to change our Gemfile and our _config.yml file to satisfy these requirements. Gemfile using the terminal, nano Gemfile comment out this line by adding a ‘#’ to the beginning gem \"jekyll\"\", \"~\u003e 4.1.1\" uncomment the following line by removing the ‘#’ from the beginning of the line gem \"github-pages\", group jekyll_plugins exit and save CTRL + x y enter cool onto _config.yml pop the following lines into the file where you please: important: before pasting make sure your _config.yml does not already have any of these elements. if they do update them to reflect these values change “[ ]” to your values url: 'https://[YOUR GITHUB USERNAME].github.io' # or other github assigned domain baseurl: '/[YOUR GITHUB REPOSITORY NAME]' lsi: false safe: true source: incremental: false highlighter: rouge gist: noscript: false kramdown: math_engine: mathjax syntax_highlighter: rouge Exit and save the file as we have before. Mine looks like this now pushing to the web Almost Done. You got this. set your project to know what URL to send info to you can get this URL from your repository page git remote set-url origin [YOUR REPOSITORY URL] upload git push origin refreshing your GitHub repository page should now be populated with files. Jump to settings Scroll down to the GitHub Pages section and select Master where the None dropdown is. Save. This should generate a message and a link that looks like this. Your site is ready to be published at https://calmcoconut.github.io/test/. follow the link and try it out on your cellphone editing the theme for your purpose I highly recommend the tutorials offered by CloudCannon on Jekyll. They have included both video and written formats. The cover most use cases. Follow this link for the blogging setup tutorial. Common Problems I am greeted with a 404 error when I click the link something has gone wrong either with your local Gemfile or _config.yml file OR you have not uploaded to GitHub. redo the Configuring to GitHub’s liking section then reupload to github by issuing the following commands in the terminal. git remote set-url origin [YOUR REPOSITORY URL] git add . git commit (write any message and hit enter after running this) git push origin The site loads but it has no images or looks like a 90’s website Very annoying problem caused by how the CSS and images are referenced. if you know anything about HTML it is a simple fix. Otherwise try the following: open the _includes folder in your project find the head.html file open and edit any href tag to start with the following {{ site.baseurl }} instead of absolute paths. for example: \u003clink rel=\"stylesheet\" href=\"{{ site.baseurl }}/assets/css/style.css\" / save but do not exit. push your changes by running the following commands git add . git commit (write any message and hit enter after running this) git push origin clear your browser history and refresh your website (this is to clear the cache).","date":"2020-09-08","permalink":"/blog/jekyll-introductions/","summary":"Jekyll is a great tool if you want the simplicity of a static website but with more complicated functionality. It offers a load of plugins and maintenance saving methods. The primary advantages are: templating variables and loop functionality support for GitHub pages (a free webhosting platform for anyone with a GitHub account) plugins, database free solutions, and niche cases If this is tempting strap in and I’ll describe my weekend setting up Jekyll.","title":"GitHub Pages with Jekyll's Static Web Framework"}]