I think that the divide between coding the details and describing the flow of a program is so large that a programming language could benefit immensely from keeping them conceptually separate. This belief has led me to design a new programming language - Glow - that has this separation at its core.
In the big picture, we want good documentation.
In the details, documentation is often outdated and redundant.
In the big picture, uncontrolled side effects and mutable global variables lead to an unmaintainable mess where hidden assumptions are everywhere.
In the details, say within one or a handful of functions, mutation can be efficient, idiomatic and easy to understand.
In the big picture, we often want to annotate functions with types, even if the language can infer them automatically or does not need them.
In the details, we don’t want to litter the code with explicit types, making it harder to read and write and harder to change implementation details.
In the big picture exceptions are dangerous beasts. They are essentially gotos. Non-local behaviour that can make a system hard to reason about and that can give suprising failure modes.
In the details, exceptions are a convenient way of signalling that the input to a non-total function did not live up to its contract or that the surrounding system (hardware, DB, etc) are not in the assumed state. If we can signal these breaches of contract compile-time, using the type system, this is great. Unfortunately not everything can be statically proven.
In the big picture, visual programming is very natural. It is, in fact, so natural that we often make flowcharts of how systems work. It would be better if these flowcharts would actually be the system, rather than an incomplete, possibly outdated description.
In the details, visual programming is just an inconvenient gimmick. IMHO. It may change one day.
A component is a function that may have input arguments, but not return arguments. It also has zero or more input pipes, output pipes or bidirectional pipes. A component can send data to an output pipe and it can receive data on an input pipe, either by “forall” to loop until the pipe closes or “get” to block until it gets the next value. Pipes can also be bidirectional, which means that you can both send and receive. This is convenient, for example when you want to make database queries to a component.
A pipe can be closed both upstream (sender has run out of data) and downstream (receiver has found what it is looking for). Since a pipe can be closed downstream, you can compose strict pipelines that behave lazily by terminating early when they are done, yet are nicely decoupled.
If a component has only one input pipe, it is deterministic in the sense that the behaviour is identical to a pure function with a lazy list or generator as input argument. This means that it is easier to test. If we had a “peek” function that could check if an input pipe had anything new yet, the receiving component could loop and do different stuff depending on when a new value is ready, begging for race conditions. If a component has more than one input pipe it is not deterministic in general, since “forall” can take several pipes of the same type and emit the values in the order they are produced.
Components may clean up after a pipe closes, which I will describe more in a later post in conjunction with exceptions.
A component with one input pipe and one output sounds very similar to a function. You are supposed to use a function if there is a one-to-one mapping between input and output and you do not keep state. isPrime (:: Int -> Bool) would most naturally be a function. Run length encoding, for example, would more naturally be a component.
#no arguments, one input pipe named values and one output pipe named encoding.
runLengthEncode :: Eq a => | values a || encoding (a, Int)
runLengthEncode():
oldval = get values
count = 1
foreach value in values:
if value == oldval:
count += 1
else:
put encoding (oldval, count)
oldval = value
count = 1
if count:
put encoding (oldval, count)
Ignore syntax, the use of Haskell-style type classes and the detail of what happens if there is no first value to get. When we have just one input and one output, this is equivalent to something like a generator using “yield” in Python.
I don’t think pipes need to come with any performance overhead compared to a normal function call, so they are supposed to be used a lot.
Components can be run concurrently and it should “just work”, since components cannot share mutable data. If you need shared mutable data, a component that keeps state and has more than one input pipe will no longer have any guarantees of determinism and could be used as (or wrap), for example, a database.
The same component could also be run concurrently in parallel against the same input pipe, as long as the input and output order does not matter. This problem is inherent in parallelism. In MapReduce, the problem of the unordered output pipe is solved by attaching a key to each indata value, which can also be attached to the output.
When connecting two components, the type of connection indicates how the output component is run. As mentioned in the checklist, above, you can also imagine GPU connections. Since all effects except local mutation are handled as pipe communication, a Glow component should not need many constraints to target a GPU.
No side-effects are built in to the language. Even stuff like current time and print are handled by a C FFI. A FFI must be wrapped as a component, so all effects are clearly visible as pipe communication. Since you might want the same output component to handle, for example, logging or file handling in many components, unattached output pipes with the same name and type are merged to one output pipe when two components with dangling outputs are connected.
Since side effects are often slightly troublesome when testing, it is my intention that a component connection can later be overriden (or monkey-patched, if you will) by a mock-component with the correct type. This means that the file system, database or clock for an entire application can be overriden for testing purposes or when you want to simply switch out a component across an application. I have not yet fully worked out how namespaces, etc, should work in this context.
We use two types of files to program Glow. The detail files, which can contain anything, and the overview files, which may only contain constants and how components are connected to each other. An overview file may not use macros.
Both are editable with any text editor, but the overview file can also be edited visually as a vectorized flowchart (vectorized to zoom in on details). This should have a number of benefits. - The overview chart is good documentation that is never out of date. Not for a library API, but for a system or application. - You can design programs on your tablet or phone, by touch. Fill in the details when you get to a keyboard. - You get a visual REPL for debugging and testing. Change constants (read more below) and watch changes, live. - The flowchart may also serve as a simple control panel for the application in production.
It is important that you should never need a special application to view the overview file. It must be perfectly legible as text, even when generated by a flowchart-editor.
The overview file for a simple web scraper. Not final syntax:
LinkQueue :: queue
Scraper :: urlGet timeout=5
TheExtractor :: extractor
LinkQueue.get -> Scraper.urls
Scraper.data -> TheExtractor.data
Scraper.error -> Print.in
TheExtractor.urls -> LinkQueue.put
The lower case variables, like “queue” are components, but since a component can be in several places in a system, connected to different stuff and called with different arguments, each component needs an instantiation (one could imagine syntactic sugar for anonymous component instantitions. “Lambdas”). The word after the dot is the channel name. “->” is a standard connection. The flowchart for this file would be three objects connected in a circle, with “Scraper” also having a print connection.
Note that what you would work with in this interface is not types and class hierarchies as you might in a modelling tool, but the actual component instances. The static data. Component instances and other data that is generated dynamically, either compile-time or runtime, would not show up. Only the concrete, static data, components and connections can be in the overview file. This is also why no macros are allowed in the overview file - how would an interface edit component connections that are generated compile time and not written explicitly in the original source?
During runtime, the same flowchart-like interface could be used to add visualisers of data flowing through different pipes. Graphs, counters, latest value, etc, could be monitored. Perhaps color to indicate relative traffic.Just as objects in Python have a str or repl method, when they need to be printed, standard Glow data types could have html-representations rendered in the interface.
I believe that the component+pipes concept lends itself very well to Functional Reactive Programming. A side-effect of this is that statically defined data could have controllers that dynamically changes the program behaviour during runtime. I’ll try to flesh out my ideas for that later.
This was just a first overview of Glow. I have not yet written about the type system, the module system, exceptions and contracts (yes, they are tightly coupled), metaprogramming and “sublanguages”, how functional reactive programming fits with components or, you know, the actual syntax. Most of that, except syntax (meh), module system (probably something close to MixML) and parts of the type system (higher-order stuff related to MixML or type classes) are already designed.
Also, if it was not obvious, there is no compiler or anything else yet. Not a shred of code. I know that a compiler (and visual editor!) is a serious undertaking. I think that this particular programming language does not rely on any magic that makes it harder to implement than, say, Rust. I also think it would be different enough to stand out. Perhaps others are intrigued and willing to help out?
This was inspired by Bret Victor, the Haskell pipes library, Go, my experience from work and many other things. In fact, if you have not seen Bret Victor’s brilliant “Future of programming” and “Inventing on principle”, go watch them already.
]]>Yes, of course it has been done before, but I thought the idea was interesting and wanted to try it myself. I am very interested in health and longevity, so I thought I’d incorporate what I consider the most important and well-founded dietary findings in my recipe. The final recipe (let’s call it “Goop”, like the food in The Matrix) will be quite cheap compared to regular food and include only natural vegetarian ingredients and a multi-vitamin (mostly for the vitamin D).
Nutrition is complicated. The most difficult part of any new dietary idea is that humans are extremely long lived, so it takes forever to verify the long-term effects. Also, most of us are not keen to be put in cages and fed on a rigorous schedule, so you never know quite what people really eat. You can probably tell a lot from mouse studies and you can monitor known health markers in humans, but there are no guarantees. I have not even tried this diet myself yet (though I will in just a few days). If you decide to give it a try, you do it completely at your own risk.
Even if you are not interested in my final recipe for a complete nutrition shake (or shake-like substance), you might find the general discussion on what to put in your body interesting.
My goal is to design as “healthy” a diet as possible, which is at the same time as simple as possible. Palatability comes a distant third. My plan is not to consume Goop exclusively for the rest of my life, but perhaps to consume the majority of my “meals” this way. I don’t want to give up on sublime culinary experiences or that ice cream that just hits the spot once in a while. The majority of my meals or snacks currently do not fall in those categories, though. Partly it is also a fun intellectual excercise.
I currently do intermittent fasting once or twice a week. Even though it is probably just as healthy to allow yourself to eat a few hundred calories during those 24 hours, to me, it just complicates matters. It is psychologically easier just to say “stop” for 24 hours than to bargain with yourself over how much food you are allowed to eat on your fasting days. I suspect the same might be true with food intake. If your diet is extremely simple and restricted, it might be easier to follow than one with a hundred vague guidelines which will give you tastier food and more variation, but many more daily decisions and temptations.
It may also be a starting point for a later diversification or for optimizing in the “palatable” direction. We’ll see.
How many calories you need is obviously a function of many variables, including gender, age, height, physical activity and genes. Fortunately, too many or too few calories are quite easy to detect. Just weigh yourself regularly. Preferably on a scale that measures body fat percentage. I know those are not very accurate, but here we do not care much about absolute numbers, just change.
The simplest, most researched and most effective diet tuned for health and longevity must be calorie restriction. Eating 10-30% fewer calories than you “need”, but all the nutrition. With Goop, CR with full nutrient intake becomes easy. I will practice a mild CR, because full-blown CR is inconvenient.
I am almost 2 meters tall and I burn 500-600 calories a day biking to and from work. I also run regularly and do some strength training. I need more calories than most, but let’s start out with the usual assumption of a target around 2000 calories.
We get calories from protein, carbohydrates and fat. How much you should get from each group is a source of fierce debate. The safest bet seems to be that carbs should be somewhere between 30% and 50% of daily calorie intake, fat around 30% and protein between 15% and 30%. That is generally less carbs than in a regular western diet. On the other hand we are not aiming for so few carbs as to induce ketosis which may help people lose weight somewhat faster, but does not seem generally conductive to health.
Eating too much protein can also be unhealthy. The liver and kidneys are put under strain and you may lose calcium and thus bone mass. You have to make sure you drink a lot of water and adequate calcium if you consume 1/3 of your calories from proteins. In the very well researched Fantastic Voyage, Ray Kurzweil and Terry Grossman advocate 35% of calories from protein in general and 55% for the rather extreme diet for those with diabetes II. Eating more protein than 1g/kg body mass will not make you gain muscle faster.
When it comes to fat, it is probably good for you to have ratio of Omega 6 / Omega 3 consumption somewhere between 2:1 and 1:1. The modern diet has way too much Omega 6, which is inflammatory and bad for your heart.
Regarding carbs, we want to have slow carbs that the body digests slowly. This helps your body keep your blood sugar and insulin levels steady, which protects you from diabetes and wards of hunger. In a normal diet we also want a lot of fibers. Fibers makes you digest more slowly and feed your intestinal bacteria. If you are not used to food with high fiber content, you need to increase fiber intake slowly, since you need to build up your gut flora. Goop contains 50-60 grams of fibers each day, which probably takes some getting used to. A common guideline is that your diet should contain at least 30g fibers per day.
When it comes to protein, things get a little tricky. Normally you would just want protein with an amino acid profile close to your own, which makes meat, eggs or whey protein powder a good choice, unless you are lactose intolerant.
Calorie restriction, see above, seems to induce slower aging. Interestingly, so does protein restriction, with some caveats. Even more intrestingly, restricting just the amino acid methionine (a part of normal protein) also seems to induce slower aging (see methionine restriction). Methionine is an essential amino acid, so we can’t just cut it out of our diet, but restricting it is possible, by eating certain vegetarian proteins and not too much of them. Soy is one protein source that has comparativel little protein. It has gotten some bad press, but it is probably safe. Nevertheless perhaps pea protein is the most attractive alternative.
Long term methionine restriction is AFAIK completely untested in humans, so I wouldn’t advocate it or try it myself. I do think it is prudent to make sure you don’t get excess methionine, though.
I practice intermittent fasting (IF) once or twice a week, fasting 24 hours on water and green tea. The evidence for the benefit of different kinds of IF, both in animal studies and humans (think religious fasting) has reached a thoroughly convincing level.
The first 1 - 3 times I was really hungry, but the body quickly adapts and it becomes easier. There is however an alternative possibility, which may give the same benefits. Carbohydrate-concentration. Instead of fasting, you only carb-fast. That is, you consume all of the carbohydrates for each day in one meal. It does not matter which one.
Carb concentration is less well researched than intermittent fasting, but the effects on blood sugar are fairly well understood and it looks promising. I might try carb concentration and see how convenient it feels, since it is quite easy to divide the components of a shake anyway one sees fit. It is not something I will try immediately, though.
We need vitamins to live. It is fairly well-known how much we need to survive, but the optimum levels are a source of debate. Many (probably all) vitamins are anti-oxidants, protecting your body from free radicals. According to the free-radical theory of aging, this should be very important. At the same time studies don’t really find life-extending effects from consuming large amounts of anti-oxidants. At the same time, meta-studies that have found deterimental effects seem quite silly, e.g including patients that take large quantities of vitamins for some serious ailment.
Here is a list of the recommended daily allowances.
If we cover the vitamin need with a multi-vitamin, it is probably best to take it in divided doses with “meals” (at least fat), for proper uptake. There are multi-vitamins made to be taken in divided doses, for example these [Two-per-day capsules] (http://www.lef.org/Vitamins-Supplements/Item01714/Two-Per-Day-Capsules.html). Otherwise you can just split one, if it is dry.
Almost all multi-vitamins come with the alpha form of vitamin E, which some say is a problem. This might displace the other forms of vitamin E, and actually make you deficient. In Goop, I will get plenty of gamma-tocopherol from the flaxseed oil, so it is probably OK. Also, this nutritional researcher notes that it might be a confusion of cause and effect and that low gamma-tocopherol may just be a indicator that something else is wrong.
Vitamin K is not a part of most multi-vitamins, so we need that through our diet.
Here are the RDAs for minerals. You could get most of them from a decent multi-vitamin, but those below usually need other sources.
Phosphorus deficiency is very rare, so there are almost no phosphorus supplements for humans (but plenty for horses).
Calcium is usually not included in a mutli-vitamin in enough quantities, just a little to go with the vitamin D.
Potassium is a lethal poison if you consume too much of it, so you have to be very careful when supplementing. This is why potassium pills are rare and usually far below the RDA.
Iron is an oxidant, so you don’t want to get too much. You also don’t want to be deficient, making you anemic and lethargic. Menstruating women need more than men.
Copper, like iron, should not be consumed to excess. I have never seen a multi-vitamin with more than 50% RDA (RDA is 2g) copper.
Sodium and chlorine are easily obtained from table salt. Most things get tastier with a little salt anyway.
Phytochemicals (or phytonutrients) are difficult. They are the tens of thousands of possibly protective substances in plants. They are not absolutely essential to life, but they may protect against cancer, stroke, macular degeneration, inflammation and all sorts of things.
WebMD suggests that the most important are carotenoids, ellagic acid, flavonoids, resveratrol, glucosinolates and phytoestrogens.
It is very difficult to come to some sort of conclusion. The effects are certainly not obviously beneficial. Carotenoids, resveratrol and glucosinolate seems the most interesting, to me, though especially resveratrol is controversial.
The matter is further complicated by the issue of hormesis. Protecting from oxidant damage is good, but if you protect too well it seems to make it worse. For example, the positive effects of excercise (which inflicts oxidation damage to your body) can be negated by anti-oxidants. It seems that only if you stress your cells just enough, good things happen.
In my personal opinion hormesis is the single most confounding factor of longevity science. It is just like with training a muscle. If you train it too much, you may overtrain and it becomes weaker instead of stronger. If you don’t get any oxidative stress, you don’t “train” your body and trigger the beneficial heat shock responses and gene expressions, but if you get too much you “overtrain” and just break down your cells. Since so many different things adds oxidative stress and so many other things protect from it and since it seems almost impossible to know (I suppose blood tests could one day be developed) if you get too much or too little, it is very hard to know what anti-oxidants will do to your body.
Where possible and not too expensive, I will use organically grown ingredients, to avoid pesticides. I don’t think the benefit is large, so I won’t go to special stores or pay a premium of more than 10% or so. Oat, broccoli, berries and tomatoes are the ingredients below that I think might benefit from not having pesticides.
This adds protein, calcium, potasisum and some possibly beneficial gut bacteria.
This is the main source of low GI-carbs, copper and iron. It is also a good source of phosphorus and potassium. The fiber will make you feel satiated longer and in particular the beta-glucans in oat, which lowers cholesterol, in particular LDL. According to the Wikipedia link above, beta-glucans may also boost your immune system and have some anti-cancer properties. Also, it is a whole-grain that contains no gluten, which is trendy to avoid even amongst non-celiacs because of its allegedly inflammatory nature. I don’t think the final verdict on gluten is in yet. Bear in mind, though, that some people with celiac disease are also allergic to oats.
This is the main source of fat and that which restores the Omega 3 - Omega 6 balance. Flaxseed oil is a rich source of alpha-lipoic-acid and some people take it as a nutritional supplement. Strongly anti-inflammatory.
150g is supposed to be the average weight of one stalk of broccoli. Exact dosage is not terribly important, but it is the main source of vitamin K, so not below 75g. Broccoli is a “leafy-green”, which counts as the most healthy of the vegetable families. It is rich in phytosterols, which fight cholesterol. It also mildly anti-inflammatory.
Almonds control blood sugar and makes you feel full longer. Mildly anti-inflammatory.
Besides the five main ingredients, I have also added four flavorings.
10g cinnamon, which is most famous for regulating blood sugar and lowering LDL.
20g cocoa powder, which are rich in flavonoids, are linked to health benefits like lowering coronary heart disease and stroke risk. Also it tastes nice.
10g sun-dried tomatoes. 10g is about five dried tomatoes. I suppose I could use fresh tomatoes as well, but the drying process preserves the nutrients and makes them easier to transport and handle. Tomatoes contain lycopene. Tomato consumption has been associated with decreased risk of certain cancers.
100g frozen unsweetened berries. Mostly bilberries, but any berry will do. Full of phytochemicals.
I don’t know yet how I will mix these flavorings. Perhaps I will just throw them together. Perhaps I will keep them in separate meals.
If it needs to be sweeter, I will add stevia which must be far and away the best sweetener. Wikipedia: “Current research has evaluated its effects on obesity and hypertension. Stevia has a negligible effect on blood glucose, and may even enhance glucose tolerance”.
Goop contains very little salt, so I’ll need to add 5-10g. How much salt you lose when working out seems to vary between individuals, but you lose roughly 1g per liter sweat and sweat roughly 1 liter from a 1 hour run. 30-50% of the population are sensitive to too much salt and may get high blood pressure. For the rest, it does not seem to make a difference.
The RDA for minerals are easy enough to satisfy, but vitamin D is damn near impossible to get enough of from natural sources. The only possible exception is fatty fish, but I don’t want that in a shake… If you live in a dark country and/or spend your working hours inside, like I do, getting enough vitamin D is even more important. Goop as it stands, also lacks vitamin A, but that could be easily remedied with a carrot a day. I will take a daily multi-vitamin, but with a carrot, that could probably be downgraded to just vitamin D.
Vitamin C is unstable over time in the presence of water and I think others may react with iron, so it is probably best not to add vitamins to the mix, but swallow them separately.
Goop contains loads of soluble fiber, which amongst other things is good for lowering cholesterol. The high fiber content (56g) means that my stomach will have to get used to it gradually, by building up suitable gut bacteria. It also means that I have to drink a lot of water.
This comes to 2131 calories per day, with 198g carbs, 105g fat and 76g protein. The food is very anti-inflammatory and has a low glycemic load. The oat bran I use seem to have a slightly different nutritional value than those in the databases, so YMMV.
For a physically active male, even if he would want mild calorie restriction, this is probably too few calories. There is room for adding more carbs and protein, but preferably not more fat. Fruits, carrots, beans, protein powder and lean meat are possible additions. I suppose recovery drinks or bars after exercise is one simple, if somewhat expensive and sugary, way to compensate with more carb and protein calories. I will experiment a bit with this.
If I wanted less calories, let’s say for dieting, I would cut up to half the almonds, half the flaxseed oil and 100g of the oatbran. It is not supposed to be healthy to lose more than 0.5 kg (1 pound) per week, which is about 600 calories per day below your normal intake, so don’t go overboard.
I will just mix the ingredients and some water together to a shake or drinkable substance. I will try to mix just a little, since a smooth goo would raise the glycemic index. I still want to see oats. For variation, oat brans (say 200g), water (3 dl, pour over when boiling), oil (at most ½ dl), stevia and cinnamon or cacao as a flavouring can be blended (once again, not too smooth) and spread thinly and baked in the oven in 150 degrees C for 50-60 minutes, for a dry, not quite delicious but nutritious cookie. Since it is dry, it will be edible for many days. The low temperature will not oxidize the oil or destroy other nutrients.
I will also eat sugar-free gum after meals, to make sure that my gums get some workout. Also a clean mouth is imperative for a healthy heart.
As an experiment, I will consume Goop exclusively for a few weeks (at least three) and measure blood pressure, weight, body composition (if I can find my body composition scale), resting heart rate, mental ability, athletic ability and general well being continuously. A few people I know have expressed interest in doing the same. It would be interesting to measure various markers from my blood as well. Unfortunately, where I live this is not really offered as a separate service but rather as part of a complete health exam, which is quite expensive to do twice in succession. I will probably do it afterwards, though.
I will not go cold turkey from normal food immediately, but increase gradually, mainly to make sure I can handle the fiber content.
Adding nootropics and stimulants, like the original Soylent guy did, is also interesting. However, to avoid complicating things, I will add this later. I don’t really know which substances, but at least ginkgo biloba.
]]>/var/log/
you will most probably have logs that have grown too large and rolled over. Per default your system logger gzips and stores a few of the older ones and finally when they get too numerous, it just deletes them. Same thing for log handlers in most languages, for example Python’s RotatingFileHandler. Backups are usually also handled the same way, when you don’t want to store every backup.
That is almost never what I want. If I store only N backups, I don’t want them to be only the very latest. If they are close in time they will be more similar and in some sense contain less information than backups that are spread out over time. Of course the newer ones are probably on average more interesting to me, so I don’t want them evenly spread over time. The following simple algorithm is my suggestion for a better way to handle rotating logs and backups.
If we call the day the very first backup is made “day 0”, the current state can be defined as a list of integers. If we currently have backups from day 0, 15, 20, 25 and 28, this is represented with the list [0, 15, 20, 25, 28]. Let us say that we want a maximum of 5 backups, then when we add the backup for day 29, we have to decide which backup to discard. We do this by rating each of the 6 possible (since we have 6 different numbers to potentially discard) configurations with a fitness function and chosing the best one. A lower score is better.
The optimal fitness function will be different from case to case. In essence it should be a balance, set by a parameter, between how valuable it is to have recent data and how interesting it is to have the data well spread out. As an example of a parameterless logarithmic fitness function, consider the following function, which rates one configuration by punishing each point by how far it is from it’s ideal logarithmic position:
1 2 3 4 5 6 7 8 9 |
|
I have stored the code in an online interpreter called repl.it. You can try it out by clicking the Play button and then typing expfit([0, 15, 20, 25, 28], 29)
and for example compare with replacing your most recent backup with todays, expfit([0, 15, 20, 25, 29], 29)
.
To simulate how it would look after a certain time, I use the following code (also loaded in the session above):
1 2 3 4 5 6 7 8 9 10 |
|
Run it by simulate(10, 100)
which should yield [18, 30, 44, 59, 70, 84, 92, 96, 99, 100]. That list looks like rather a nice set of backups after 100 days, to me.
Visualising this seemed like a perfect excuse to try out Elm which is a purely functional programming language which can handle input and output with the cool Functional Reactive Programming technology. I have put the resulting simple simulation here.
I have a Github project called checkpoint with source files for Python, Haskell and Elm here.
]]>It feels good, helps me relax and it makes my mind feel clear, perceptive and sharp afterwards. It was only recently that I started doing it in conjunction with programming. The match was so good, that I felt the proselytic urge to share what I had found. My example is programming, but it can obviously be any intensive, possibly creative, mental task, such as writing, studying or playing Yahtzee.
In the 60s and 70s all sorts of fantastical and simply untrue claims were made about meditation. Unfortunately that can make people zone out when they read about recent research of higher quality that shows many real effects. See for example this Wikipedia page on meditation research.
Meditation has, among other things, been shown to increase happiness and well-being and physically change structures in the brain related to those things. It improves short-term memory. It may decrease blood pressure and risk of heart attack.
But you don’t actually have to care about any of those things. The effects after a 15 (or possibly 10 if you’re really in a hurry) minute “successful” meditation are so obvious that you should be able to evaluate if it is worth it to you, on that alone. Many do longer than 15 minutes. 30 minutes or more is not unusual. But perhaps you have a busy day - 15 minutes is enough.
Before settling down to meditate, decide on what you want to work on next. If there is some creativity or problem-solving involved, start by very quickly going through the problem in your mind, just long enough so that you have put what needs to be done within what constraints into words.
Now here’s the trick - don’t solve or design anything yet. Fight that urge. Let those thoughts vanish for now. It is especially important that you don’t think about the task during the actual meditation. Your subconscious will take care of that.
Afterwards you will be in a mentally refreshed state, ready to jump in and create. It feels different.
Meditation has always worked well for me as a cure for procrastination. If you need to do something that you have been putting off, it is easy to convince your mind that you might do it even better after some meditation. Easy, because that let’s you avoid the task even longer. However, promise yourself that you will do it right after you are done.
Sit for how long you want. If you get impatient after a while and long to do something, great! Just stop and do your task. Right after meditation you will be in a very special state. Facing that task, as long as it is well-defined, will probably no longer feel like anything special at all.
When I write “meditation”, I mean evoking the relaxation response through mental silence. The basic concept is really stupendously easy. 1) Just sit. 2) And don’t have an inner dialogue.
First part you can do, right? I suppose you can lie down as well, but we are not going for sleepy here. Thus sitting seems to convey the right sense of calm wakefulness. Also, if you are doing this in an office, sitting meditation in your chair might be slightly unusual, but getting down and lying on the floor will be too full on eccentric for most people.
But the second part. No inner dialogue. That usually scares people. “I can never do that”. “Even if you think about not thinking, that is thinking too”, etc. This is where various techniques come in. You will have to find out what works for you.
The most important thing to know is that you will have thoughts. Your inner dialogue will notice the silence and try to kickstart all sorts of new interesting internal conversations. This is not failure or you doing something wrong, it is what brains do. Just notice what happens and, no matter how tempting and interesting that thought seemed, let it pass. It will come back to you when you are done. Redirect your attention to something else. How good it feels to breathe out, for example. The longer you sit, the more space it will be between these attempts of your brain to start the dialogue again. Also, as you meditate more often, your thoughts will get sparser quicker.
When you start out, or when you pick up the habit after a long hiatus, you will have lots of meta thoughts of the type “Hmm.. how am I doing?”, “Is this right?”, “This does feel kinda good” and “OMG, my mind was totally silent for a bit there!”. That, too, is normal. When you catch yourself doing it, don’t judge. Just let the thought go.
It tends to be easier if you close your eyes, I think. But feel free to gaze at something calming or hypnotic or just into the distance. For something to focus on besides the mind’s chatter, try one or two of the suggestions below.
One technique is to focus on your breathing. In through your nose, out through your mouth. Slowly. Focus on how it feels. When words come, return to your breathing. Some people imagine breathing in energy or “good stuff” or whatever. Some people count their breaths to 10 and then over from 1 again. I don’t use that myself, because counting feels, to me, slightly like dialogue. It is effective at stopping other words, though.
Imagine you are a mountain. A patient, wise Japanese one. Sit like a mountain. Or, imagine that your mind is a completely still lake or pool. No ripples. Calm.
Imagine a spot of light in the middle of your forehead. Or maybe a laser. Shine it.
Compassionate meditation is an alternative that can feel good. Imagine a small sphere around you. Wish everything within it well. Give everything within compassion and love. Slowly expand your sphere. Smile and breathe.
Getting started can be the tricky part. One way to help this is to borrow techniques from hypnosis. For example, with each slow breath you may image yourself taking one step further down a ten step stair that leads to a door. When opened, the door leads to a calm nature scene that you have chosen in advance. You sit down and start your meditation.
Also it helps if you are in a reasonably calm state to begin with. If you are all wound up, mind racing, maybe stressed about something, it will be much harder to let yourself settle down and relax.
The most effective way I know of reaching a meditative state is through sound. Specifically, through brainwave entrainment. I know. Just the word “brainwave” makes it sound like such a load of bullcrap.
Just like with meditation there are some weird claims about entrainment, like being able to overcome all sorts of maladies, heal wounds faster, etc. Ignore those things. If any of those benefits exists at all, they are just secondary effects of being able to relax and sleep better.
What certainly is real, though, is that our brain sends out electromagnetic waves of various frequencies. Depending on what state we are in, different frequencies dominate. Here is a table of different frequencies and when they dominate. Meditation happens in the alpha and theta regions.
What is also real, is that listening to auditory pulses of specified frequencies makes your brain emit those same frequencies stronger. Thus, listening to pulses of theta or alpha frequencies (4 - 13 Hz) makes you emit more of those. Of course the association between relaxation and alpha waves might not go both ways. This might just be a mixup of cause and effect and making the brain emit more alpha waves might not make you more relaxed.
Well, studies show that they do. Less interesting to you, perhaps, is that anecdotal evidence from myself and everyone I know that have tried it (including my infant girl, who I put to sleep that way a few times..) is that it makes you go into a meditative state (or, if you like the terminology better, elicits the relaxation response) faster than anything else. It might just be placebo, but given the evidence above, it is probably not. Also, it will work on the first try, so it really is very easy for you to try it out for yourself.
There are many programs that help you put together these sort of frequency curves, add background noise and stuff. Neuro-programmer 3 Home is very good, but only for Windows (rumoured to work on Linux + Wine) and a tad expensive. I recommend Gnaural, which gives you very detailed control, is free open source and works on Win, Mac and Linux.
There are many builtin examples, but I have posted a file that Gnaural can read, with a 15 minute 4-5 Hz meditation with isochronic pulses for headphones here. After the meditation phase is done (you will know without a doubt when that phase is done, because the higher frequencies will gently wake you up) I have put in 30 minutes of 40 Hz. If it helps you with your productive phase, let it run. If it gives you a headache, turn it off.
Another good thing about entrainment is that it tells you when you are done, so you don’t have to wonder about how long you have been sitting.
So, in conclusion, don’t put it off. Take 15 minutes and try it right now. Then tell me in the comments what you thought.
]]>If-statements are easy - just use the ternary ?: operator or, if you want to show off, template specialization. But the only way to loop with these restrictions is by using recursion. Furthermore, neither clang 3.1 nor GCC 4.7 (nor the current build of GCC 4.8) support tail call elimination in these constexprs, so normal linear loops will still eat stack space if we loop for a while. Also, the standard recommends that the default maximum recursion depth should be 512, which means that if we want to do something silly/fun/interesting compile time, we have to mess with proprietary compiler switches to get the program to compile. No fun.
In this post, I show one way of working around those limitations.
But first - why would one want to do constexpr meta programming, when we already have template meta programming? Constexprs and templates are almost exactly as powerful, except that template meta programming is lazy, which some might think fits better into a functional style. A more important difference is that template meta programming can work with types, which means that we can use it for cool type-level correctness stuff. So, once again, why would we use constexprs? 1) Constexprs are evaluated several times faster in the compilers I know of, which can be important. 2) The syntax is much nicer.
Simple recursion is not a problem:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
This program will reach a depth of at the most sqrt(220), which is 210 = 1024, and since we check at most slightly less than half of those, we will be fine. Since 220 - 1 is not a prime number, we will be even more fine. However if we try check if 231 - 1 is prime, the compiler will refuse to do so. In this case we can fix it by increasing the maximum constexpr evaluation depth for our compiler, but in general that might take too much RAM, so lets do our own tail call elimination with continuation passing style and a trampoline instead.
This way, we have a trampoline function that takes a CPS function as an argument and loops, continously calling the continuation returned from the previous call.
In order to use a trampoline, we still need an infinite or near
infinite loop for the basic trampoline function. This is where
exponential recursion comes in. The recursion in rec_isprime
behaves
sort of like a linked list - each invokation links to the next. If
each rec_isprime
statement instead called two rec_isprime
, which in
turn called two other, etc, we would get a call graph that was more
like a binary tree than a linked list. This way we would not reach our
maximum recursion depth until we visited 2512 nodes and we would
never blow the stack!
Here is such a function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
This program will visit 224 - 1 = 16777215 nodes. On my normal desktop computer with clang 3.1 this program took 27 seconds to compile and the process uses no almost memory at all. With GCC 4.7.2 it compiles in 0.2 seconds! This is because GCC uses memoization for both templates and constexprs, so it will instantly see that the other count call is unneccessary and transform our 16 million node tree to a linked list of depth 24 again.
That is sort of cheating, so let’s change the function slightly:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Now memoization will not work. Clang takes 26 seconds and still uses no memory. GCC surprises us again, now taking 44 seconds and using over 3 gigs of RAM! If we increase MAXD to 25, GCC will again use twice as much RAM. I don’t know if this is because of memoization or something else. I have reported it as a bug to GCC.
Still though, it works!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
|
As you can see, we are allowed to create objects with constexpr constructors in a constexpr, so we can create containers like linked lists and trees. You can create maps, (simulated) vectors and sets on top of trees, which means that anything is possible. In truth, prime number calculation is not very exciting, but this post is running long as it is, so a compile-time CPS implementation of Game of Life or something will have to wait for next time.
Now, imagine the cheating possibilities in The Computer Language Benchmarks Game ;). Yes, yes, I know it can be done in some other compiled languages as well. Template Haskell and the Lisps come to mind.
]]>With a combination of C++11 and the Boost library, I think that it is possible to write code in a style that is almost as painless as in a modern dynamic language like Python. I also think that is not so well known how much C++ has changed for the better, outside the C++-community. Hence this post.
As an example, I have taken the first interesting excercise from Dive into Python, fileinfo.py, and converted it to C++, trying to remain as faithful as possible to the original code.
fileinfo.py
implements a simple MP3-metadata printer, which is built so that it will be easy to add other metadata printers in the future. For the Python code, see the previous link and for my commented C++ code see here:
If you remove my gratuitous commenting and the includes, you will notice that it is more or less as succinct as the Python code.
Perhaps more importantly, it is also as safe. No pointers to point at bad places and leak memory and no buffers to overflow. There is much more to why modern C++ is more safe and less memory leaky than it once was, besides the added emphasis on a more functional style, for example raw pointers are actively discouraged (use smart pointers instead) and arrays (not vectors!) are now finally in the standard library, so we use array<int, 10> instead of int array[10].
This program is actually the basis of a presentation I gave at work, which had more explanations on the features used. It only touches the surface on what you can do with C++11 You can read more about the new features in C++11 in the biggest changes in C++11 and why you should care and of course on Wikipedia.
Herb Sutter, who is chair of the ISO C++ standards committee and thus perhaps not completely unbiased, had this to say on the relase of C++11:
Now with C++11’s improvements that incorporate many of the best features of managed languages, modern C++ code is as clean and safe as code written other modern languages, as well as fast, with performance by default and full access to the underlying system whenever you need it.
I think it is almost there. For example, the language is still too large, so in a new project you have to have a good code standard, that decides well on which parts should be used and how. The standard library, even including Boost, is still a bit weak in some areas, like downloading an URL. Also the lack of a proper package manager, like pip/PyPi, hurts.
]]>This is a guide on why you need it and how you install, configure and use it. Sometimes just with links to the relevant sites.
This is written partly for my colleagues, who I think would benefit from using Zsh instead of Bash on their desktops and on our servers.
Though I have used it for 10+ years, I am far from a Bash specialist. Some of these things can be enabled in Bash, but AFAIK it is not implemented quite as well.
File based tab completion is great and all, but zsh has tab completion for everything. It has knowledge about an impressive number of tools and scripts. It knows which commands git takes, which hosts are in my hosts file for ssh, which users my system have when I write chmod, available packages to apt-get, etc. Using [tab] when writing commands is a bit like static type checking, since if you don’t get a completion you are probably writing your argument type in the wrong place.
For common use cases it is easy to write tab completion specifications for your own scripts.
Globbing means command line parameter expansion. For example ls *.html
. Zsh has it’s own globbing language. You can sort and filter by exclusion or inclusion on name, size, permission, owner, creation time. Everything.
1 2 3 4 5 6 7 8 9 10 |
|
These examples happily borrowed from Zzappers Best of ZSH Tips, Z shell made easy and Zsh-lovers man page. Skim through them all, when you have decided to give Zsh a try.
Loadable modules are modules that give your shell additional functionality. Sort of like importing a library when you code. They can make the filters above even more interesting. For example expressing date constraints in a natural format. There are examples of using modules in the Zsh-lovers man page and full documentation in the Zsh Modules Documentation.
Zsh does not care if I write a filename in lowercase or mixed or whatever. When I try [tab] it will first try to complete on the exact match and then use a case insensitive match. Great! It also has spelling correction built-in in other places, suggesting which command you might have meant, etc. You don’t want full spelling correction on files though (deactivated per default). That is just annoying.
Aliases are nice, but global aliases are words that can be used anywhere on the command line, thus you can give certain files, filters or pipes a short name. Some examples:
1 2 3 |
|
If you want to give a directory an alias, you use hash. hash -d projs=~/projects/
Zsh also has suffix aliases, which means that you can tie a file suffix, let’s say “pdf” to a command, for example xpdf. alias -s pdf=xpdf
Now if you just type the name of a pdf file, it will be displayed with xpdf. Similar to suffix aliases, if you turn on AUTO_CD, typing the name of a directory cd:s to it.
OK, so now you know that you need to try Zsh out. What do you do? Simple. Head over to oh-my-zsh and follow the intructions. When installing Zsh, you should customize two things.
Extravagant prompts have become a badge of pride for Zshellers. It is quite easy to write your own prompt. I have:
Note how you can control both the left part and right part of the line. You can also make multi-line prompts, but I like to conserve screen estate.
On the left side I put stuff that are of interest almost all the time. My username, the name of the computer, the last two parts of the directory tree, If I am in a git or hg repository and which branch (very useful to keep from screwing up) and finally if there are uncommitted code (the X turns in to a neat V when there is nothing to commit).
On the right side, I put the number of jobs running from this terminal, free memory (good reminder on servers) and average CPU load during the last 5 minutes, as reported by uptime
. CPU load is expressed as number of CPUs utilized, so to make it meaningful, I also put the number of CPUs in paranthesis after the uptime value. This is also mostly useful if you have several servers with different number of CPUs. If the uptime value exceeds number of CPUs, you know that you have problems. Finally I put a timestamp. Perhaps you think “How silly, I have a clock on my desktop!”, but the point is not to tell the current time, but that I can scroll back and see when I started a command and how long it took. It keeps a log. Another good thing with keeping colorful stuff on the right side of the prompt is that it makes it easy to scroll through your terminal output and find commands, when your last compile spewed out 200 lines.
Usually the window is much wider than in my screenshot, so you don’t often run into the right part of the prompt, but if you do, Zsh will magically remove it before you reach it, so it won’t look cluttered.
This is the code for my prompt. For some reason Github overrides my syntax highlighting settings when I give the gist a filename, so my gists are unnamed today:
You can take it or any other from the theme gallery (you should visit that now, it is full of themes and colorful screenshots of what you can use immediately after installing oh-my-zsh) as a base if you want to write your own. You can call all the scripts and commands that your heart desire to produce the prompt output.
Currently, my prompt is not part of the oh-my-zsh distribution (I have not made a pull request. Perhaps I should?), so if you want to use it, just download it and copy it to ~/.oh-my-zsh/themes/gurgeh.zsh-theme.
A good prompt really is a great help.
Oh-my-Zsh has a lot of great plugins. You can read more about them there. I found it easiest to just read through the simple source code of the ones that interested me. These are the ones that I use (from my ~/.zshrc file):
plugins=(git mercurial autojump command-not-found python pip github gnu-utils history-substring-search)
To use autojump on Ubuntu, you need to sudo apt-get install autojump
. That enables you to just write j [directory]
and it will jump to the most frequently used directory with that name. A great way to navigate, which naturally can use tab-completion. It just takes some time for your fingers to get used to it. Autojump is not limited to Zsh, of course.
My Zsh configuration is nothing special, you can check out part of it here:
I probably should add some more aliases.
In Bash, we often use PgUp to search through the command history. In Zsh you just write part of the command and press Up. This will let you cycle through all command lines that contain what you have written, not just those that begins with it. If you don’t write anything Up works as usual, by cycling through all commands.
Write zsh_stat to get statistics over which commands you use the most. Use jumpstat to get statistics over which paths you use the most.
Well, that’s it for now. Make the switch now! And browse the resources I have linked to for more tips.
]]>It was fairly easy, just follow the instructions on Octopress. If you are running Ubuntu, don’t apt-get rbenv
, use the latest version from Github instead. This is actually what the Octopress instructions tells you to do, but I ignored it and I am now happy to have survived.
The Octopress instructions for deploying to Github is also straightforward enough, as are the Github instructions for using your own domain name.
I used an external script to migrate my Blogspot articles to my new site. It worked OK, but formatting was lost and the comments became static text. If you browse them, you will see that they currently look kinda ugly. When I have fixed them up a bit, I will begin forwarding all my old posts from Blogspot to fendrich.se.
There are not an abundance of themes yet, but you can always design one yourself. Picking colors and doing basic layout is easy. If you are design impaired, like I, there are a few ready-made here. Currently I use Darkstripes.
Also, a good blog has comments (and a good blog reader comments!), so I enabled Disqus.
Google Analytics support is built in, but just to be hip, I use Clicky instead. It was simple to install. Just put the tracking code in /source/_includes/custom/after_footer.html
.
I created my own favicon from my Twitter picture by using this tool and stuck it in the /source directory. Possible because I am using Darkstripes I had to edit /source/_includes/head.html
and change favico.png to favico.ico.
That’s basically it. Hopefully this means I blog more. And better. And that the next post contains code. And perhaps even a pretty image. Or graph. And full sentences.
]]>> echo -en $’\x6e\0000\x5f\x69\x6e\x69\x74\0000\x6c\x69\x62\x63\x2e\x73\x6f\x2e\x36\0000\x66\x66\x6c\x75\x73\x68\0000\x73\x74\x72\x63\x70\x79\0000\x66\x63\x68\x6d\x6f\x64\0000\x65\x78\x69\x74\0000\x73\x74\x72\x6e\x63\x6d\x70\0000\x70\x65\x72\x72\x6f\x72\0000\x73\x74\x72\x6e\x63\x70\x79\0000\x73\x69\x67\x6e\x61\x6c\0000\x5f\x5f\x73\x74\x61\x63\x6b\x5f\x63\x68\x6b\x5f\x66\x61\x69\x6c\0000\x73\x74\x64\x69\x6e\0000\x72\x65\x77’ > myfile
> echo -en $’\x69\x6e\x64\0000\x69\x73\x61\x74\x74\x79\0000\x66\x67\x65\x74\x63\0000\x73\x74\x72\x6c\x65\x6e\0000\x75\x6e\x67\x65\x74\x63\0000\x73\x74\x72\x73\x74\x72\0000\x5f\x5f\x65\x72\x72\x6e\x6f\x5f\x6c\x6f\x63\x61\x74\x69\x6f\x6e\0000\x5f\x5f\x66\x70\x72\x69\x6e\x74\x66\x5f\x63\x68\x6b\0000\x66\x63\x68\x6f\x77\x6e\0000\x73\x74\x64\x6f\x75\x74\0000\x66\x63\x6c\x6f\x73\x65\0000\x6d\x61\x6c\x6c\x6f\x63\0000\x72\x65\x6d’ >> myfile
> echo -en $’\x6f\x76\x65\0000\x5f\x5f\x6c\x78\x73\x74\x61\x74\x36\x34\0000\x5f\x5f\x78\x73\x74\x61\x74\x36\x34\0000\x67\x65\x74\x65\x6e\x76\0000\x5f\x5f\x63\x74\x79\x70\x65\x5f\x62\x5f\x6c\x6f\x63\0000\x73\x74\x64\x65\x72\x72\0000\x66\x69\x6c\x65\x6e\x6f\0000\x66\x77\x72\x69\x74\x65\0000\x66\x72\x65\x61\x64\0000\x75\x74\x69\x6d\x65\0000\x66\x64\x6f\x70\x65\x6e\0000\x66\x6f\x70\x65\x6e\x36\x34\0000\x5f\x5f\x73\x74\x72\x63’ >> myfile
> echo -en $’\x61\x74\x5f\x63\x68\x6b\0000\x73\x74\x72\x63\x6d\x70\0000\x73\x74\x72\x65\x72\x72\x6f\x72\0000\x5f\x5f\x6c\x69\x62\x63\x5f\x73\x74\x61\x72\x74\x5f\x6d\x61\x69\x6e\0000\x66\x65\x72\x72\x6f\x72\0000\x66\x72\x65\x65\0000\x5f\x65\x64\x61\x74\x61\0000\x5f\x5f\x62\x73\x73\x5f\x73\x74\x61\x72\x74\0000\x5f\x65\x6e\x64\0000\x47\x4c\x49\x42\x43\x5f\x32\x2e\x34\0000\x47\x4c\x49\x42\x43\x5f\x32\x2e\x33\0000\x47\x4c\x49’ >> myfile
from optopus import ga, stdgenomes
#Now we choose a representation. We know that the answer to the puzzle must be some permutation of the digits 1 to 9, each used nine times.
init_vect = sum([range(1,10)] * 9, []) # A vector of 81 elements
genome = stdgenomes.PermutateGenome (init_vect)
#I made a few functions to calculate how many conflicts a potential Sudoku solution has. I'll show them later, but for now let us just import the package. I also found a puzzle somewhere and put it in the PUZZLE constant.
import sudoku
solver = ga.GA(sudoku.ga_sudoku(sudoku.PUZZLE) , genome)
#And now, when we have supplied the GA with a fitness function (ga_sudoku, which counts Sudoku conflicts) and a representation (genome), let us just let the solver do its magic.
solver.evolve(target_fitness=0)
DIM = 9
def one_box(solution, i):
"""Extract the 9 elements of a 3 x 3 box in a 9 x 9 Sudoku solution."""
return solution[i:i+3] + solution[i+9:i+12] + solution[i+18:i+21]
def boxes(solution):
"""Divide a flat vector into vectors with 9 elements, representing 3 x 3
boxes in the corresponding 9 x 9 2D vector. These are the standard
Sudoku boxes."""
return [one_box(solution, i) for i in [0, 3, 6, 27, 30, 33, 54, 57, 60]]
def splitup(solution):
"""Take a flat vector and make it 2D"""
return [solution[i * DIM:(i + 1) * DIM] for i in xrange(DIM)]
def consistent(solution):
"""Check how many different elements there are in each row.
Ideally there should be DIM different elements, if there are no duplicates."""
return sum(DIM - len(set(row)) for row in solution)
def compare(xs1, xs2):
"""Compare two flat vectors and return how much they differ"""
return sum(1 if x1 and x1 != x2 else 0 for x1, x2 in zip(xs1, xs2))
def sudoku_fitness(flatsolution, puzzle, flatpuzzle=None):
"""Evaluate the fitness of flatsolution."""
if not flatpuzzle:
flatpuzzle = sum(puzzle, [])
solution = splitup(flatsolution)
fitness = consistent(solution) #check rows
fitness += consistent(zip(*solution)) #check columns
fitness += consistent(boxes(flatsolution)) #check boxes
fitness += compare(flatpuzzle, flatsolution) * 10 #check that it matches the known digits
return fitness
def ga_sudoku(puzzle):
"""Return a fitness function wrapper that extracts the .genes attribute from
an individual and sends it to sudoku_fitness."""
flatpuzzle = sum(puzzle, []) #just a precalcing optimization
def fit(guy):
return sudoku_fitness(guy.genes, puzzle, flatpuzzle)
return fit
Mindpixel was a web-based collaborative artificial intelligence project which aimed to create a database of millions of human validated true/false statements, or probabilistic propositions.Unfortunately the project is now defunct, since the founder Chris McKinstry committed suicide on 23rd January, 2006.
specify goals and weight them , acquire combine breakdown and refine strategy.
A strategy specifies goals, their desirability and at what likelihoods to take what actions on what (set of) conditions.
Devising strategies can be broken down into:
creating and assessing conditions for actions,
weight of goals, estimates of cost for actions,
estimates of effectiveness of actions, finding related strategies,
taking strategies apart,
combining strategies,
covering contingencies,
evaluating strategies
The reason the github activity is low is more silly. I am currently in something between the design and implementation stage, writing Python code with a few pseudocode elements and a lot of prose. For some reason, I have not considered this semi-code "commit-worthy".
I promise a github update this week.
It is geared towards very technical users. It takes input tasks as snippets of code and gives a set of inputs that makes the function output true. This is called function inversion and is a fairly simple way of describing puzzles and technical problems.
If it turns out to be a useful system for solving these types of tasks (a big IF - no one has really been able to achieve that). It would be a very good base on which to build something that can communicate with non-technical users and interact with our fuzzy world. That is not it's primary purpose, though.
Actually, I will remove that. That source code is not for human consumption yet. It is just test cases for analyzing source code, written in an odd Lisp dialect. No actual code relating to implementing either any of the algorithms I write about or the Scheduler.