Tuesday, November 18, 2025

Implementing CP Prolog - 8, an epiphany

 On Sunday, I wrote: During the week, I had been thinking about how I had become addicted to programming this interpreter; yesterday was certainly addiction, but it wasn't much fun. At the moment we're at the stage of clutching at straws with no fresh ideas of how to solve this problem that is down to memory management, something that Delphi - and expecially the very stable Delphi 7 version - is supposed to handle for the user.

Last night when I got into bed, I started thinking about the parser - not a recommended way of falling asleep, I note - when I had an epiphany. At some stage on Saturday, CoPilot had suggested saving the value that the parser was returning in a global variable or similar. This isn't a very good idea in terms of computer science and we ignored it. But last night, I realised that pointers to all the terms were being saved in the program's heap so that they could be disposed of during garbage collection. All I needed to do after parsing a clause in the rule's body was to walk down this heap, looking for the first (actually, the last) term of a specific type - this is the value that should be saved. CoPilot would never have 'thought' of this.

What does this mean in simple terms (pun not intended)? Let's say that there is the clause female (X). The parser will read the token female, and because of the bracket, it will know that this token is the functor of the clause. The token X will be then be read and a new term allocated (and stored on the heap) for this variable. Then a term will be allocated (and again, stored on the heap) for a compound item, consisting of the functor (female) and its arguments (X). So if I want to get the value of this term later on, it will found at the top (or close to the top) of the heap.

This solution, whilst quite brilliant, is sidestepping the actual problem that is preventing the proper execution of the code - but I'm prepared to accept the pragmatic solution if it keeps me moving forward. Incidentally, after using the value provided by walking the heap, the entire body was displayed correctly, which is a big step forward.

Next is checking that this rule can be resolved, just to ensure that everything is as it should be. Then will come the task of parsing a fact that has nested clauses such as owns (noam, cd (unhalfbricking, 'fairport convention')). I'm fairly sure that all I will have to do is change one statement in order to achieve this. I wonder whether the result of parsing these nested clauses will also display the same bug that I've just fixed (or at least, worked around). 

But I'm going to beat my addiction and not touch this material for a few days.

Internal links
[1] 2037



This day in blog history:

Blog #Date TitleTags
14518/11/2008Lonely at the topMIDI, Randy Newman
30518/11/2010How to save money when ordering books from abroadBook depository
30618/11/2010Alesis Q49MIDI, King Crimson, Antibes
52118/11/2012Warming up for DBA examDBA
77718/11/2014Enron's spreadsheetsDBA, Excel
155218/11/2022Fairport newsFairport Convention
168718/11/2023The musical group reconvenesMusical group
186218/11/2024Shel Talmy, Peter Sinfield RIPObituary, King Crimson, Van der Graaf Generator

Sunday, November 16, 2025

Implementing CP Prolog - 8, a problematic start

What, I hear you say, a weekend without an update on the status of CP Prolog? Well, yes, that's because I spent many frustrating hours over the weekend trying to finish the first part of a new version - and not succeeding.

The impetus for the new version was a set of clauses that I saw in a book, along these lines 

owns (noam, cd (unhalfbricking, 'Fairport Convention')). owns (sarit, cd ('best of', 'Dire Straits')); owns (noam, book ('nightwings', 'Robert Silverberg')).

In other words, I want to add the possibility of nested clauses, and also have quoted names. This will enable me to get a list of all the items that I own, or a list of cds, or even a list of cds by Fairport Convention.

To this end, CoPilot built a recursive descent parser along with a tokeniser that worked perfectly with prefix operators. I was initially pleased as this parser would replace the rather ad hoc parsing that existed so far. Unfortunately the pure model of prefix Prolog is ruined by those pesky infix mathematical operators, so first I had to add some code to the tokeniser to recognise these, and then some code to the parser. This last part was quite difficult; there was something not quite right with one of the functions which of course was the one that dealt with the infix operators. I added a patch which seemed to fix the parsing of some expressions but not all. 

I ran out of time on Friday afternoon so I had to continue on Saturday morning with a fresh brain. I soon found the correct implementation of the fix (if you really want to know, the parser was confusing the comma between clauses with the comma between operands), and later found that this code caused problems right at the very end of the list of clauses so another condition had to be added. This was my work, not CP's; I had to 'argue' with it until it conceeded that I was correct.

The parser now reads a list of clauses well, although we haven't trained it on those nested clauses at the beginning of the blog - these are on the 'head' side of a rule and not the 'body' side. I am hoping that one simple change will allow the program to read those nested head clauses.

After I finished with the parser, I idly thought to display the clauses that had been parsed, just to check that everything was correct. And not only was the output incorrect, it had somehow missed the first two clauses out of five, the third was repeated as the fourth and only the fifth was correct! So CoPilot and I started a debugging marathon of several hours that has yet to be completed. It's completely weird that for every clause except for the final clause in a list, one function can be seen to return a certain value, but that value gets mangled by the time that it arrives at its destination. Very strange. CoPilot was convinced for some time that the problem was caused by something overwriting something else, but I told CP that it was wrong, for if that were the case, then all the output would be identical. Again, it eventually conceeded that my explanation was correct

There wasn't much else to do yesterday as it was pouring with rain (30.2 mm) so we continued and continued. During the week, I had been thinking about how I had become addicted to programming this interpreter; yesterday was certainly addiction, but it wasn't much fun. At the moment we're at the stage of clutching at straws with no fresh ideas of how to solve this problem that is down to memory management, something that Delphi - and expecially the very stable Delphi 7 version - is supposed to handle for the user.

Once the parsing and memory management is fixed, then I will check whether displaying the knowledge base needs improving. And only then will it be possible to start on improving the goal solver.



This day in blog history:

Blog #Date TitleTags
64716/11/2013Song festivalMIDI, Kibbutz, Song writing
135816/11/2020Vinyl log #32Vinyl log, Heron
168616/11/2023Counting beats with Van der Graaf Generator (4) - Whatever would Robert have said?Van der Graaf Generator
186016/11/2024New CPAP mask (2)CPAP

Saturday, November 15, 2025

New CPAP mask

I received my new Joyce Cara CPAP mask on Wednesday and immediately its effects were felt, reducing the number of apneic events from nearly 20 per hour to only 3 (and there's room for improvement). My original hypothesis - that I discarded - was that the mask needed to be replaced; this is the real reason for the increase in apneic events. The mask came with the straps already attached; all I had to do was tighten them. I think that in previous years I have had to attach the straps myself, and my three left hands mad this process difficult. 

Last year, I wrote that the company was offering the mask for 799 NIS on its website; the price is now 749 NIS. I spoke to a sales person about this and discovered that this was the price of the mask itself, without the flexible pipe that connects to the mask and brings the air from the machine, and without the filters for the machine. I didn't use to change the filters much in the past (although I do now) and I don't know how much the pipe degrades over a year - if at all - but as I'm not paying anyway, it didn't make much sense to try and save. As my wife said when we were talking about some other health issue, don't scrimp on health.

My weight has also reduced by 300 g this week - not a huge amount, but still considerable. The family came over for dinner last night and we talked a little about the diet. I said that I wasn't used to eating at 7 pm and indeed I had stomach ache after dinner. They asked whether I was hungry in the evenings - I said that I frequently feel an urge at tea time for a little something but I can successfully resist this. I don't know what I'm going to do the next time we have a Friday night dinner: either eat much less or else cook a portion of fish and eat that. Friday night communal dinner is one of the great Jewish traditions.

The first rain fell yesterday and woke me up at 4:45 am. Shortly after I got up and took the dog for her morning walk. It started raining again at about 11 am and didn't stop until the evening, so fitting in an afternoon or evening walk was problematic. Before 8 am yesterday, 0.4 mm fell, and until 8 am this morning another 4.9 mm. Not huge figures but it's a start. The rain is supposed to finish by tonight. 

Internal links
[1] 2024
[2] 1853



This day in blog history:

Blog #Date TitleTags
14415/11/2008Adele
30415/11/2010Project Management lecturesMBA, Project management
51915/11/2012Inside the DOCU program (2) - saving and loading rich textProgramming, Delphi
52015/11/2012Inside the DOCU program (3) - Saving screenshotsProgramming, Delphi
90315/11/2015Going to see a man about a dogDog

Monday, November 10, 2025

Implementing CP Prolog - 7A, supplemental

I wrote on Saturday1: I had to take out several of the instrinsic functions that were added last week, so now these have to be restored, and there's no guarantee that the code that worked a week ago will work now because several aspects have been changed and tightened up.

I restored the intrinsic functions necessary for the 'time_in_minutes' query2 on Saturday evening. No syntax errors occurred when I did this, but running a query like ?- time_in_minutes (03:30, X). should give the result 210. Unfortunately the result was 270. Looking at the trace of the query, it was clear what happened. The final goal of the rule is X is H * 60 + M, where X is the result, H the number of hours and M the number of minutes. Instead of calculating (H * 60) + M (i.e. (3*60) + 30), the interpreter was calculating H * (60 + M), or 3 * 90. 

So we had to reimplement the parsing of a line that could have any number of infix operators. CoPilot went through about four different implementations until we finally got something that would work correctly. On and off through the evening, I considered the final implementation and was sure that it was more complex than necessary. There was also a bubble sort at the beginning of the function that could be avoided with a little preplanning (and it's just occurred to me that the bubble sort would run each time the parsing routine was called which is several times: the sort should have been moved out of the function). 

I gave my conclusions to CoPilot and they were sort-of incorporated. At least another two versions were required before the statement was parsed correctly. It's all due to operator precedences  - remember from junior school: multiplication and division before addition and subtraction. Just to make things more complicated, (I quote) In Prolog, operator precedence is a numerical value (typically between 1 and 1200) that determines the order in which operators are evaluated within a term. Higher precedence values indicate weaker binding, meaning operators with higher precedence are considered "further out" in the structure of the term, while lower precedence values indicate stronger binding. For a language of logic, it seems illogical that a higher number has what one would normally call lower precedence. This required several loops to run backwards, although it occurred to me afterwards that it would be more sensible to change the operators table once again so that the loops could run normally. Ultimately it doesn't make any difference.

Once again, I have to say that for all the sophistication of CoPilot, sometimes it makes silly mistakes and sometimes the results aren't what were required. One "endearing" feature that I have noticed is remarks like "there's a problem with your code at such-and-such a place". Sometimes it's typing errors, but more often those are mistakes that CoPilot made in early iterations.

Internal links
[1] 2033
[2] 2029



This day in blog history:

Blog #Date TitleTags
77310/11/2014Literature review: second draft completedDBA
98510/11/2016Data collectionDBA
109010/11/2017INTQUANT and REALQUANTPriority tips
185510/11/2024F25 Cell phone stand with wireless speakerMobile phone

Sunday, November 09, 2025

James D. Watson RIP

James Watson was one of the pair 'Crick and Watson' who elucidated the structure of DNA in 1953. This is, without doubt, one of the defining discoveries in science during the 20th century and created the entire industry of biotech. The advantage that Crick and Watson had was that they were both intellectual magpies, coming to DNA after having worked in other areas. On the other hand, they were fortunate in being the first to unravel the structure; colleagues such as Maurice Wilkins and Rosalind "Rosy" Franklin contributed in major ways.

 In 1967 Watson wrote the book "The double helix" that recounts the story of how Watson started work on DNA, how he met Francis Crick, then Wilkins and Franklin, how they progressed and stumbled and progressed and stumbled. It's illuminating to read this book from the perspective of 2025, especially regarding the inter-personal reactions. All three men were condescending, at the least, to Franklin who made the important contribution of the X-ray photographs. 

I suspect that I read "The double helix" while I was at school, or at least at university. I'm fairly sure that we covered DNA, RNA and protein synthesis as part of the A-level biology curriculum, and this was new science - only twenty years after the discovery. But it wasn't until 2004 that I bought a paperback copy of the book (1999 edition) and I have the 2012 annotated version as an e-book. 

It was this book - or rather, the discovery that the book describes - that opened the way for a great deal of my reading in the past few years. Without C&W (not country and western!), there would have been no "The code breaker" by Walter Isaacson, telling the story of Jennifer Doudna and her work on the CRISPR system of gene editing, or Doudna's own book, "A crack in creation", or any of the biochemistry books by Nick Lane that deal in part with how life could have started and how RNA could have been built initially. I also read a biography of Rosalind Franklin whose name escapes me at the moment. Doudna didn't have good words for Watson who had become controversial in later life.

Gene editing was a common topic in science fiction - fiction that later became facr - as in Robert Silverberg's "Up the line", for example.

An obituary can be read here.



This day in blog history:

Blog #Date TitleTags
42709/11/2011Feeling the pressureMBA, Finance
118509/11/2018Improving a solutionProgramming, Priority tips
143909/11/2021The department of bright ideasProgramming, Problem solving
185409/11/2024Beneath a scarlet skyLiterature, Italy

Saturday, November 08, 2025

Implementing CP Prolog - 7

Calculating the factorial function is the poster boy of recursion. It's very easy to define the factorial of a positive number: if the number is 0 then the factorial is 1, else it's the number itself times the value of the factorial of the number less 1. In other words, the factorial of 1 is 1 * factorial (1 - 1) = 1, and the factorial of 2 is 2. More interestingly, the factorial of 3 is 6 (because that's 3 times 2), and the factorial of 4 is 24 (because that's 4 times 6). This can easily be defined in an imperative language such as Pascal as follows.

function factorial (n: integer): integer; begin if n = 0 then factorial:= 1 else factorial:= n * factorial (n - 1) end;

So simple yet so bad, as calculating the factorial of a number such as 10 will cause a great deal of stack space to be used because of the recursion. An iterative calculation is just as simple and executes with a constant and minimal amount of stack space, as well as being faster.

function factorial (n: integer): integer; var i: integer; begin result:= 1; for i:= 1 to n do result:= result * i; end;

But what does the factorial function look like in Prolog?

factorial (0, 1). factorial (N, F):- N > 0, N1 is N - 1, factorial (N1, F1), F is N * F1.

This matches the initial description that I gave. The factorial of 0 is 1, otherwise assuming that N is greater than 0, the result (F) comes from multiplying the number itself (N) by the factorial of N - 1 (F). The rule looks a bit strange but that's because of the syntax that Prolog requires. 

Last week's installment had the interpreter solving several goals where the final goal included an assignment ('is'), multiplication and addition. A great deal of work was spent on getting that 'is' functor to do what it was intended to do. Calculating the factorial depended on that 'is' functor as it is called twice on every invocation. It turns out that it wasn't correct. 

Before I could tackle the factorial, I wanted to ensure that the 'add' 1 function that I added a few weeks ago still worked. It didn't, so first we had to spend no small amount of time getting this to work again. I knew that 'add' would be a goal on the path of getting the factorial to work.

Let us say that I spent several exceedingly frustrating hours yesterday and today trying to get my interpreter to calculate the factorial. I would run a test and show CoPilot the results. 'Add this', it would return. So I added something more and sometimes it would improve the situation but more often that not would make no change. There are parts of the interpreter (especially handling the 'is' functor) that went through several changes. Sometimes the changes would make things worse, meaning that I had to restore code from previous versions. At one stage, CoPilot said 'do A', then when that didn't work, 'do B', then 'do A'. Exceedingly frustrating. It completely ruined the 'resolve' function that lies at the heart of Prolog, so I had to restore this from last week's code (I back everything up religiously).

CoPilot of course was not running blind. I would run diagnostics and sometimes had enough understanding to see what the current problem was. A key breakthrough was made by me when we saw that that a specific block of code from CP (which had already been tweaked and improved on a previous version) was not doing something that it was supposed to do. That insight almost completely solved the problem. Finally, after having added and removed the same lines time and time again, CP said that You need to ensure that after the rule body succeeds, the rule head variables are unified with the goal arguments. (Does that make any sense? Why wasn't this suggested before?) This was the final piece in solving the puzzle. Now my interpreter can calculate factorials.

In getting this far, I had to take out several of the instrinsic functions that were added last week, so now these have to be restored, and there's no guarantee that the code that worked a week ago will work now because several aspects have been changed and tightened up. It seems that 'maintenance work' (i.e. restoring functions that had been removed to make things clearer) takes more time than actual development work.

I have two more goals to solve (deliberate Prolog speak), although these are not concerned with the external functionality of the interpreter. I want to implement 'garbage collection': in the course of a single query, a certain amount of memory is allocated which is not needed after the query completes and so should be released (and the calculation of factorial (10) will require much more memory than factorial (1)). I know that this doesn't make much difference when one has megabytes of memory, but it's good housekeeping.

In a similar manner, there's a small improvement that should be made in handling rules. Going back to the original family tree example2, there were various functors used, like 'parent', 'male', 'female', 'father', 'mother' and 'grandparent'. If one is trying to find a fact that matches 'male', for example, there should be no need to iterate over all the 17 facts/rules in the database, but only those where the functor is 'male'. I know that this is done by means of a symbol table, where each functor is assigned an index: finding a suitable fact/rule can be done by comparing two index numbers as opposed to invoking the 'expensive' resolution functionality. I suspect that this will be relatively simple, but what seems to be simple is often complicated.

Internal links
[1] 2023
[2] 2014



This day in blog history:

Blog #Date TitleTags
64508/11/2013Sorting in Excel via Delphi automationProgramming, Delphi, Excel, Office automation
90008/11/2015Conceptual changeDBA
90108/11/2015900 blogsMeta-blogging
143808/11/2021DBA updateDBA
155108/11/2022First rain of the yearWeather
185308/11/2024New CPAP maskCPAP

Thursday, November 06, 2025

New smart watch

Several years ago, I posted about a smart watch that I received for free from my health fund by virtue of walking a lot and accumulating points in their application. I had seen that my daughter has some form of smart watch (not from the health fund) and this planted a seed in my mind that maybe it was time again to try with a smart watch. Maybe they've got smarter over the past five years. 

The watch required 69,900 points (and an extra 60 NIS) for purchase (a site selling this watch in Israel has it at 423 NIS, discounted from 499 NIS); a week in which I achieve my walking goal gives me 1,500 points, and most days I earn an extra 30 points, so a normal week will see my point count increase by about 1,600 points. That means that I've been saving for about 44 weeks or ten months. At the moment my weekly goal is 'only' 58,500 steps a week, or 8,357 steps a day. There are days when I barely make this target and days when I far exceed it. As the purpose of the application is to encourage exercise, the weekly total is supposed to increase, but it's been about the same for the past few weeks. I could easily walk more, but if I do this, then the target will increase and then maybe I won't be able to make the weekly target. So I'm gaming the system at the moment by trying to make the daily target; normally once a week I will walk far more, so then on Saturdays I try to walk as little as possible in order not to increase the target. 

Once I received the watch, the usual trauma started: how do I charge it? How do I make it work? The charger cable comes with a USB plug at one end and a magnetic strip at the other that connects to the watch (but only one way around). After charging the watch for a few hours, I turned it on and tried to figure out how to use it. The instructions were mainly a set of pictures, too small to be useful, so they didn't help. I contacted my daughter, but she has a Samsung watch and so she could only give advice: the clock on the watch should synchronise once I run an application on my phone.

The booklet came with a QR code, but when I initially scanned it, an app for an online bank started installing. Reading the fine print a bit closer, it talked about installing 'Smart life', but this turned out to be an app that controls smart devices within the home. Eventually I scanned the QR code again and this time another app called 'Smart life' (or rather, 'Oplayer smart life') from Synergy Innovations started to install. It wasn't clear at first how it would connect to the watch: I could see the bluetooth icon on the watch but when I turned on the phone's bluteooth and started scanning, no watch could be found. Eventually the app connected to the watch and since then everything that appears on the watch also appears on the phone.

What does the watch do? Apart from telling the time (useful at night) and measuring steps, it also measures my pulse and oxygen saturation. Supposedly it also measures something to do with sleep, presumably light and deep sleep. It might also measure a few more things, such as swimming, but that can wait for several months.

How accurately does the watch measure steps and pulse? At the moment of writing, Samsung health says that I have walked 3,532 steps today, whereas the watch says 3,427. My pulse last night as measured by the sphygmomanometer was 80 bpm whereas the watch said 87 bpm. There was a similar gap this morning. Intriguingly, I can see a graph of readings starting at midnight although I can't see what each point represents. At midnight and until I got up at 5:30 am, the pulse was low; it then increased just before 6 am which is when I was walking the dog, then decreased again. 

The screenshot from the phone app gives an indication of the pulse ("heart health") without actually showing the values. Similarly with sleep: the app only started measuring at midnight (and yesterday there seems to be no sleep at all) so I 'slept' only 5 hrs 12 minuts (which is approximately correct if it's only from midnight); I think that light sleep was from 00:00 until 00:17 (17 minutes), then again from 01:35 until 02:53 (78 minutes), but after that there aren't enough times given that line up with the start or end of periods. To me, it looks about 50% each. 

I have just discovered that if I press on that graph (on the phone), I can get details for a day, a week or a month. So I spent 2 hours and 4 minutes in deep sleep and 3 hours 8 minutes in light sleep. I was in deep sleep for 39% of the time measured, which is considered normal, whereas I was in light sleep for 61% which apparently is high. That's slightly confusing: the deep sleep should be considered low if the light sleep is high. But where's my sleep from 9 pm the evening before? 

I can also see that my pulse decreased from 61 bpm to about 50 bpm during the night. Pressing on the pulse segment and requesting 'more data' gives me a reading for about once every half hour, including yesterday evening. Apparently my pulse was at 146 bpm yesterday evening at 20:26; as I was watching television at the time, one can only assume that my pulse increased because I was so digusted at the news. At 20:58 the pulse was back down to 68 bpm and decreased to 51 bpm at 22:34.

This is all very interesting, but not too valuable if the data don't match those measured in other ways (and at the moment, they don't!). On the other hand it can give indications and trends. I hope that the problem with measuring sleep will sort itself out.

Internal links
[1] 1419



This day in blog history:

Blog #Date TitleTags
5906/11/2006ShoppingVan der Graaf Generator, Peter Hammill, Musical instruments, Keyboard
21506/11/2009Eliza Carthy, "Red"Morse, Eliza Carthy
30106/11/2010Trains and mealsCooking, Trains, Slow cooker
108806/11/2017Forty years agoPersonal, Sandy Denny, Heron
118306/11/2018Intermediate thesis submitted!DBA
143606/11/2021Opening Word from a thread and displaying a fileProgramming, Delphi, Threads
155006/11/2022Appearances in my school's ChroniclesPersonal, Bristol Grammar School
185106/11/2024More dopamineProgramming, Blog manager program
185206/11/2024Guy Fawkes nightIsrael, Yuval No'ach Harari

Tuesday, November 04, 2025

Squamous Cell Carcinoma (SCC)

Today I had the operation for removal of a growth on my neck to which I referred1 six weeks ago. We arrived at the hospital far too early, and would have arrived even earlier had we taken advantage of a short cut that I wasn't sure about (the 'new' road 16 that surfaces very near the hospital). It was like waiting for an airplane: first we waited for the check-in counter to open, then I checked in, then after another wait, the plastic surgery clinic opened and a nurse checked me, then we waited some more then eventually another nurse called me into surgery.

The operation - if one can call it that - was very similar to all those that I've had before, although this time it seemed to be more involved in that a larger area of skin seemed to be removed. There was cauterisation (creating the smell of burnt flesh) and self-dissolving stitches, followed by the application of a relatively large bandage.

The tissue that was excised was sent to a laboratory within the hospital, and after a wait of nearly two hours, the result arrived: a squamous cell carcinoma had been removed. What's the difference between BCC and SCC?

  • Basal Cell Carcinoma (BCC) arises from basal cells located in the lower part of the epidermis.
  • Squamous Cell Carcinoma (SCC) develops from squamous cells found in the upper layers of the epidermis.

To you and me they're more or less the same. At the moment it's difficult to tilt my head because of the huge bandage, but tomorrow it will come off and life will go back to normal.

Internal links
[1] 2001



This day in blog history:

Blog #Date TitleTags
21404/11/2009HejiraRandy Newman, Joni Mitchell
42504/11/2011Coffee addicts (Millennium trilogy)Films, Meg Ryan, Steig Larsson, Time traveler's wife
42604/11/2011User defined menusProgramming, Delphi
143404/11/2021Sleeping deeplyCPAP, MP3, Binaural beats, Sleep
154804/11/2022Redesigning the 'blogs' programProgramming, Blog manager program

Saturday, November 01, 2025

More apneic events

I wrote1 ten days ago about the high number of apneic events that my CPAP machine had been recording. I had two hypotheses for these high numbers: the mask is reaching the end of its life, and the lack of amitryptiline. 

Well, today I reviewed the numbers for the past week, and whilst they're not quite as bad as those from early October, they're still far too high. I've been taking amitryptiline every night, so I can see that if it did have an effect, it's only minor. I'm going to order the new mask tomorrow, as we're now in November, and last year's mask was bought in November: I'm entitled to a free mask once a year. I don't think that the mask will have much of an effect either.

A third hypothesis occurs to me: maybe my weight loss is effecting the apnea. Since writing that blog, I've dropped another half kilo from my weight. I looked at my records and saw that I was nearly the same weight in May 2023: I had lost weight in a similar manner to that of today (although I soon started putting it back on), but there seems to have been no effect on the number of apneic events. As I suffer from central sleep apnea, which is caused by the brain failing to send proper signals to the muscles that control breathing, it seems unlikely that weight would have any effect.

I shall try to find a 'sleep doctor' whom I can consult.

Internal links
[1] 2024



This day in blog history:

Blog #Date TitleTags
77201/11/2014Undoing textual changesProgramming
154501/11/2022Big cloudWeather