This feed omits posts by rms. Just 'cause.

SACRAMENTO, CA:

Promising his podcast listeners an engaging and enlightening conversation, California Gov. Gavin Newsom reportedly sat down Tuesday with a serial killer who targets the homeless population. "So what do you think Democrats can learn from somebody who, like you, targets the most vulnerable among us?" said Newsom, who acknowledged that while he and the murderer might not see eye to eye on the best way to eliminate the homeless, he was grateful for the opportunity to exchange ideas and perspectives. "You hate the homeless, I hate the homeless. People have been very hard on you, but I think at the end of the day, we all really just want the same thing. So, do you wear their skin?" At press time, podcast listeners were praising the killer for his civility.

Previously, previously, previously, previously, previously, previously.

Posted Wed May 14 01:25:54 2025 Tags:
What is the deal with those e-bikes with the giant-ass motorcycle tires? Why is that a thing? How does it make sense to carry all that extra mass?

(And if these delivery shitheads could stop going 20MPH on the sidewalk that would be greaaaaaat.)

Previously, previously, previously.

Posted Tue May 13 22:08:52 2025 Tags:
Hey, you know those giant glass stairs in the Apple Store? So sleek, so Apple...

So cracked. Every one of them.

They should have put a screen protector on these. I don't think AppleCare is gonna cover this.

Posted Tue May 13 22:00:43 2025 Tags:
Fucking Apple. Anyone got a theory on why Mail.app suddenly won't show me an unread badge in the Dock icon any more? No matter what I set "Dock unread count" to, nothing shows up. And, when I quit and restart, "Dock unread count" reverts to "Inbox Only" -- although the plist still shows it remaining set to my desired mailbox:

% defaults read ~/Library/Containers/com.apple.mail/Data/Library/Preferences/com.apple.mail.plist ... SelectedMailboxOutlineItems = ( "smartmailbox://6ec9a140-1950-4276-b2c6-14ce0fb6ce9e" ... MailDockBadge = 4; MailDockBadgeCurrentCount = { count = 1; }; MailDockBadgeMailbox = "smartmailbox://6ec9a140-1950-4276-b2c6-14ce0fb6ce9e";

Things that did not help:

  • Rebooting.
  • sqlite3 ~/Library/Mail/V10/MailData/Envelope\ Index vacuum
  • rm -rf ~/Library/Containers/com.apple.[Mm]ail* (which blew away my preferences).

Previously, previously, previously, previously.

Posted Tue May 13 18:51:22 2025 Tags:
Broke-Ass Stuart made a nice little video about Death Guild. Which is, incidentally, tonight and every Monday since 1993. Come on down! Your sulking corner awaits.

(You might not ever have known about this video, since it existed only on Instagram and isn't even linked to from his own web site, because that's how social media works now. I weep for the future.)

Posted Mon May 12 18:36:52 2025 Tags:

There’s a general question of what things are canonical discoveries and what are invented. To give some data answering that question, and because I think it’s fun, I set about to answer the question: What is the most difficult 3x3x3 packing puzzle with each number of pieces? The rules are:

  • Goal is to pack all the pieces into a 3x3x3. There are no gaps or missing pieces

  • Pieces are entirely composed of cubes

  • Each number of pieces is a separate challenge

  • Monominos (single cube pieces) are allowed

  • The puzzle should be as difficult as possible. The definition of ‘difficult’ is left intentionally vague.

The question is: Will different people making answers to these questions come up with any identical designs? I’ve done part of the experiment in that I’ve spent, ahem, some time on coming up with my own designs. It would be very interesting for someone else to come up with their own designs and to compare to see if there are any identical answers.

Thanks for reading Bram’s Thoughts! Subscribe for free to receive new posts and support my work.

Don’t look at these if you want to participate in the experiment yourself, but I came up with answers for the 3, 4, 5, 6, 7, 8, 9, 10, and 12 pieces. The allowance of monominos results in the puzzles with more pieces acting like a puzzle with a small number of pieces and a lot of gaps. It may make more sense to optimize for the most difficult puzzle with gaps for each (small) number of pieces. There’s another puzzle found later which is very similar to one of mine but not exactly the same probably for that reason.

If you do this experiment and come up with answers yourself please let me know the results. If not you can of course try solving the puzzles I came up with for fun. They range from fun and reasonably simple to extremely difficult.

Thanks for reading Bram’s Thoughts! Subscribe for free to receive new posts and support my work.

Posted Sun May 11 23:46:59 2025 Tags:
"I spent the last three days fighting AI bots."

"Eight-year-old me is very excited by this."

"Yeah it was less 'Judgement Day' and more 'editing actuarial tables.'"

"So not GUNHED?"

"GUNHED dot XLS."


Previously, previously.

Posted Sun May 11 09:40:42 2025 Tags:
SFPD violated the rules on overtime, repeatedly -- but they still got their money:

The San Francisco Police Department decided on its own to violate the rules limiting public employee overtime, the Board of Supes learned Tuesday. [...]

At that hearing, some of the supes questioned why SFPD was allowing officers to work as private rent-a-cops, on OT pay, for a lot more than the 500 annual hours that the city currents sets as the limit on extra work.

SFPD also defied a Memorandum of Understanding with the Department of Human Resources that barred cops who had called in sick more than twice in six months to work in the private market, under the so-called 10B program. [...]

Walton said that he's been on the board for seven budget cycles, and every year, the cops have been unable to property estimate their overtime and budget for it. I might be less charitable; one could argue that SFPD doesn't put all its projected OT in the budget because the department brass assume that the supes will just approve supplemental appropriations later. As they have, for seven years.

"We'll never have change if we keep giving them a blank check," Walton said. "We hold everyone accountable except this department. [...]

Then support it they did, 9-2, with only Walton and Fielder in opposition.

SFPD says its officers working as security guards are 'out in the community.' But mostly, they're downtown:

Businesses on Market Street, like Salesforce and Twitter, for instance, were frequent customers, as were Union Square stores like Macy's and Victoria's Secret. Officers were also spread out to a handful of retail spots elsewhere in the city, chiefly Walgreens, Target and Safeway.

Walgreens, in fact, was by far the largest user of private security hours from police officers between 2018 and 2023, and many of the blips that appear away from the downtown core are Walgreens stores. (The large bubble in Golden Gate Park? The Outside Lands music festival.) [...]

Officers working private security are considered on-duty and can make arrests. They must wear police uniforms and their badge, and carry department-issued firearms. And they make time-and-a-half: At an officer's starting salary, that's $83.49 an hour. By the time an officer is a sergeant, it's $123.54 an hour, and for a lieutenant, it's $141.06. [...]

Officers might prefer to work private security to shifts in their district stations. The fact that they can easily call out sick and, that very same day, work a private security gig, a practice that was documented extensively in a city audit last year, is a major problem, he said. [...] The program, Walton added, "is a big win for corporations, for private businesses, for overtime abuses, and not for the entire city."

Previously, previously, previously, previously, previously.

Posted Wed May 7 19:53:41 2025 Tags:

Let’s say that you’re making a deep neural network and want to use toroidal space. For those that don’t know, toroidal space for a given number of dimensions has one value in each dimension between zero and one which ‘wraps around’ so when a value goes above one you subtract one from it and when it goes below zero you add one to it. The distance formula formula in toroidal space is similar to what it is in open-ended space, but instead of the distance in each dimension being a-b it’s that value wrapped around to a value between -1/2 and 1/2, so for example 0.25 stays where it is but 0.75 changes to -0.25 and -0.7 changes to 0.3.

Why would you want to do this? Well, it’s because a variant on toroidal space is probably much better at fitting data than conventional space is for the same number of dimensions. I’ll explain the details of that in a later post1 but it’s similar enough that the techniques for using it an neural network are the same. So I'm going explain in this post how to use toroidal space, even though it’s probably comparable or only slightly better than the conventional approach.

Thanks for reading Bram’s Thoughts! Subscribe for free to receive new posts and support my work.

To move from conventional space to an esoteric one you need to define how positions in that space are represented and make analogues of the common operations. Specifically, you need to find analogues for dot product and matrix multiplication and define how back propagation is done across those.

Before we go there it’s necessary to get an intuitive notion of what a vector is and what dot product and matrix multiplication are doing. A vector consists of two things: a distance and a magnitude. A dot product finds the angle between two vectors times their magnitudes. Angle in this case is a type of distance. You might wonder what the intuitive explanation of including the magnitudes is. There isn’t any, you’re better off normalizing for them, known in AI as ‘cosine space’. I’ll just pretend that that’s how it’s always done.

When a vector is multiplied by a matrix, that vector isn’t being treated as a position in space, it’s a list of scalars. Those scalars are each assigned a direction and magnitude of a vector in the matrix. That direction is assigned a weight of the value of the scalar times the magnitude. A weighted average of all the directions is then taken.

The analogue of (normalized) dot product in toroidal space is simply distance. Back propagating over it works how you would expect. There’s a bit of funny business with the possibility of the back propagation causing the values to snap over the 1/2 threshold but the amount of movement is small enough that that’s unusual and AI is so fundamentally handwavy that ignoring things like that doesn’t change the theory much.

The analogue of a matrix in toroidal space is a list of positions and weights. (Unlike in conventional space in toroidal space there’s a type distinction between ‘position’ and ‘position plus weight’ where in conventional space it’s always ‘direction and magnitude’.) To ‘multiply’ a vector by this ‘matrix’ you do a weighted average of all the positions with weights corresponding to the scalar times the given weight. At least, that’s what you would like to do. The problem is that due to the wrap-around nature of space it isn’t clear which image of each position should be used.

To get an intuition for what to do about the multiple images problem, let’s consider the case of only two points. For this case we can find the shortest path between them and simply declare that the weighted average will be along that line segment. If some of the dimensions are close to the 1/2 flip over then either one will at least do something for the other dimensions and there isn’t much signal for that dimension anyway so somewhat noisily using one or the other is fine.

This approach can be generalized to larger numbers of points as follows: First, pick an arbitrary point in space. We’ll think of this as a rough approximation of the eventual solution. Since it’s literally a random point it’s a bad approximation but we’re going to improve that. What we do is find the closest image of each of the points to find a weighted average of to the current approximation and use those positions as the ones when finding the weighted average. That yields a new approximate answer. We then repeat. Most likely in practical circumstances this settles down after only a handful of iterations and if it doesn’t there probably isn’t that much improvement happening with each iteration. There’s an interesting mathematical question as to whether this process must always hit a unique fixed point. I honestly don’t know the answer to that question. If you know the answer please let me know.

The way to back propagate over this operation is to assume that the answer you settled on via the successive approximation process is the ‘right’ one and look at how that one marginally moves with changing the coefficients. As with calculating simple distance the snap-over effects rarely are hit with the small changes involved in individual back propagation adjustments and the propagation doesn’t have to be perfect, it just has to on average produce improvement.

1

It involves adding ‘ghost images’ to each point which aren’t just at the wraparound values but also correspond to other positions in a Barns-Wall lattice, which is a way of packing spheres densely. Usually ‘the Barns-Wall lattice’ corresponds specifically to 16 dimensions but the construction generalizes straightforwardly to any power of 2.

Posted Wed May 7 04:23:04 2025 Tags:
Debian 12.9:

# date Tue 6 May 19:05:57 PDT 2025 # sudo systemctl stop systemd-timesyncd.service # sudo date -s '2232-04-18 16:47:16' date: cannot set date: Invalid argument Wed 18 Apr 16:47:16 PDT 2232 Exit 1 # date Tue 6 May 19:06:14 PDT 2025 # sudo date -s '2232-04-18 16:47:15' Wed 18 Apr 16:47:15 PDT 2232 # sleep 30 ; date Wed 18 Apr 16:47:45 PDT 2232

The cutoff is 0x1ED5D7403.

Previously, previously, previously, previously, previously, previously, previously.

Posted Wed May 7 02:17:02 2025 Tags:
Dear Lazyweb,

How do I do an Apache rewrite but also have it show up in error_log? E.g. the following has the side effect that it is not logged, making it unavailable to fail2ban:

RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^.*$ - [GONE,LAST]

Previously, previously, previously, previously, previously.

Posted Tue May 6 20:54:04 2025 Tags:

AI can play the game Go far better than any human, but oddly it has some weaknesses which can allow humans to exploit and defeat it. Patching over these weaknesses is very difficult, and teaches interesting lessons about what AI, traditional software, and us humans are good and bad at. Here’s an example position showing the AI losing a big region after getting trapped:1

Go board showing cyclic attack

For those of your not familiar with the game, Go is all about connectivity between stones. When a region of stones loses all connection to empty space, as the red marked one in the above position just did, it dies. When a group surrounds two separate regions it can never be captured because the opponent only places one stone at a time and hence can’t fill both at once. Such a region is said to have ‘two eyes’ and be ‘alive’.

Thanks for reading Bram’s Thoughts! Subscribe for free to receive new posts and support my work.

The above game was in a very unusual position where both the now-dead black group and the white one it surrounds only have one eye and not much potential for any other. The AI may have realized that this was the case but optically it looks like the position is good so it keeps playing elsewhere on the board until that important region is lost.

Explaining what’s failing here and why humans can do better requires some background. Board games have two components to them: ‘tactics’ which encompasses what happens when you do an immediate look-ahead of the position at hand, and ‘position’ which a a more amorphous concept encompassing everything else you can glean about how good a position is from looking at it and using your instincts. There’s no fine white line between the two, but for games on a large enough board with enough moves in a game it’s computationally infeasible to do a complete exhaustive search of the entire game so there is a meaningful difference between the two.

There’s a bizarre contrast between how classical software and AI works. Traditional software is insanely, ludicrously good at logic, but has no intuition whatsoever. It can verify even the most complex formal math proof almost immediately, and search through a number of possibilities vastly larger than what a human can do in a lifetime in just an instant, but if any step is missing it has no way of filling it in. Any such filling in has to follow heuristics which humans painstakingly created by hand, and usually leans very heavily on trying an immense number of possibilities in the hope that something works.

AI is the exact opposite. It has (for some things) ludicrously, insanely good intuition. For some tasks, like guessing at protein folding or evaluating it’s far better than any human ever possibly could be. For evaluating Chess or Go positions only a handful at most of humans can be an AI running purely on instinct. What AI is lacking in is logic. People get excited when it demonstrates any ability to do reasoning at all.

Board games are special in that the purely logical component of them is extremely well defined and can be evaluated exactly. When Chess computers first overtook the best humans it was by having a computer throw raw computational power at the problem with fairly hokey positional evaluation underneath it which had been designed by hand by a strong human player and was optimized more for speed than correctness. Chess is more about tactics than position so this worked well. Go has a balance more towards position so this approach didn’t work well until better positional evaluation via AI was invented. Both Chess and Go have a balance between tactics and position because we humans find both of those interesting. It’s possible that sentient beings of the future will favor games which are much more heavily about position because tactics are more about who spends more computational resources evaluating the position than who’s better at the game.

In some sense doing lookahead in board games (the technical term is 'alpha-beta pruning’) is a very special form of hand-tuned logic. But it by definition perfectly emulates exactly what’s happening in a board game, so it can be mixed with a good positional evaluator to almost get the best of both. Tactics are covered by the lookahead, and position is covered by the AI.

But that doesn’t quite cover it. The problem is that this approach keeps the logic and the AI completely separate from each other and doesn’t have a bridge between them. This is particularly important in Go where there are lots of local patterns which will have to get played out eventually and you can get some idea of what will happen at that time by working out local tactics now. Humans are entirely capable of looking at a position, working through some tactics, and updating their positional evaluation based on that. The current generation of Go AI programs don’t even have hooks to make that possible. They can still beat humans anyway, because their positional evaluation alone is comparable if not better than what a human gets to while using feedback, and their ability to work out immediate tactics is ludicrously better than ours. But the above game is an exception. In that one something extremely unusual happened, in which something which immediate optics of a position were misleading, and the focus of game play was kept off that part of the board long enough that the AI didn’t use its near-term tactical skill to figure out that it was in danger of losing. A human can count up the effective amount of space in the groups battling it out in the above example by working out the local tactics and gets a further boost because what matters is the sum total of them rather than the order in which they’re invoked. Simple tactical evaluation doesn’t realize this independence and has to work through exponentially more cases.

The human executable exploits of the current generation Go AIs are not a single silly little problem which can be patched over. They are particularly bad examples of systemic limitations of how those AIs operate. It may be possible to tweak them enough that the humans can’t get away with such shenanigans any more, but the fact remains that they are far from perfect and some better type of AI which does a better job of bridging between instinct and logic could probably play vastly better than they do now while using far less resources.

1

This post is only covering the most insidious attack but the others are interesting as well. It turns out that the AIs think in japanese scoring despite being trained exclusively on chinese scoring so they’ll sometimes pass in positions where the opponent passing in response results in them losing and they should play on. This can be fixed easily by always looking ahead after a pass to see who actually wins if the opponent immediately passes in response. Online sites get around the issue by making ‘pass’ not really mean pass but more ‘I think we can come to agreement about what’s alive and dead here’ and if that doesn’t happen it reverts to a forced playout with chinese scoring and pass meaning pass.

The other attack is ‘gift’ where a situation can be set up where the AI can’t do something it would like to due to ko rules and winds up giving away stones in a way which make it strictly worse off. Humans easily recognize this and don’t do things which make their position strictly worse off. Arguably the problem is that the AI positional evaluator doesn’t have good access to what positions were already hit, but it isn’t clear how to do that well. It could probably also be patched around by making the alpha-beta pruner ding the evaluation when it finds itself trying and failing to repeat a position but that needs to be able to handle ko battles as well. Maybe it’s also a good heuristic for ko battles.

Both of the above raise interesting questions about what what tweaks to a game playing algorithm are bespoke and hence violate the ‘zero’ principle that an engine should work for any game and not be customized to a particular one. Arguably the ko rule is a violation of the schematic of a simple turn-based game so it’s okay to make exceptions for that.

Posted Sat May 3 21:23:58 2025 Tags:

I’ve written several previous posts about how to make a distributed version control system which has eventual consistency, meaning that no matter what order you merge different branches together they’ll always produce the same eventual result. The details are very technical and involved so I won’t rehash them here, but the important point is that the merge algorithm needs to be very history aware. Sometimes you need to make small sacrifices for great things. Sorry I’m terribly behind on making an implementation of these ideas. My excuse is that I have an important and demanding job which doesn’t leave much time for hobby coding, and I have lots of other hobby coding projects which seem important as well.

My less lame excuse is that I’ve been unsure of how to display merge conflicts. In some sense a version control system with eventual consistency never has real conflicts, it just has situations in which changes seemed close enough to stepping on each other’s toes that the system decided to flag them with conflict markers and alert the user. The user is always free to simply remove the conflict markers and keep going. This is a great feature. If you hit a conflict which somebody else already cleaned up you can simply remove the conflict markers, pull from the branch which it was fixed in, and presto you’ve got the cleanup applied locally.1

Thanks for reading Bram’s Thoughts! Subscribe for free to receive new posts and support my work.

So the question becomes: When and how should conflict markers be presented? I gave previous thoughts on this question over here but am not so sure of those answers any more. In particular there’s a central question which I’d like to hear peoples’s opinions on: Should line deletions by themselves ever be presented as conflicts? If there are two lines of code one after the other and one person deletes one and another person deletes the other it seems not unreasonable to let it through without raising a flag. Its not like a merge conflict between nothing on one side and nothing on the other side is very helpful. There are specific examples I can come up with where this is a real conflict, but then there are examples I can come up with where changes in code not in close proximity produces semantic conflicts as well. Ideally you should detect conflicts by having extensive tests which are run automatically all the time and conflicts will cause those to fail. The version control system flagging conflicts is for it to highlight the exact location of particularly egregious examples.

It also seems reasonable that if one person deletes a line of code and somebody else inserts a line of code right next to it then that shouldn’t be a conflict. But this is getting shakier. The problem is that if someone deletes a line of code and somebody else ‘modifies’ it then arguably that should be a conflict but the version control system thinks of that as being both sides having deleted the same line of code and one side inserting an unrelated line which happens to look similar. The version control system having a notion of individual lines being ‘modified’ and being able to merge those modifications together is a deep rabbit hole I’m not eager to dive into. Like in the case of deletions on both sides a merge conflict between something on one side and ‘nothing’ on the other isn’t very helpful anyway. If you really care about this then you can leave a blank line when you delete code if you want to really make sure replace it with a unique comment. On the other hand the version control system is supposed to flag things automatically and not make you engage in such shenanigans.

At least one thing is clear: Decisions about where to put conflict markers should only be made on whether lines appear in the immediate parents and the child. Nobody wants the version control system to tell them ‘These two consecutive lines of code both come from the right but the ways they merged with the left are so wildly different that it makes me uncomfortable’. Even if there were an understandable way to present that history information to the user, which there isn’t, everybody would respond by simply deleting the pedantic CYA marker.

I’m honestly unsure whether deleted lines should be considered. There are reasonable arguments on both sides. But I would like to ignore deleted lines because it makes both UX and implementation much simpler. Instead of there being eight cases of the states of the parents and the child, there are only four, because only cases where the child line is present are relevant2. In all conflict cases there will be at least one line of code on either side. It even suggests an approach to how you can merge together many branches at once and see conflict markers once everything is taken into account.3

It may be inevitable that I’ll succumb to practicality on this point, but at least want to reassure myself that there isn’t overwhelming feedback in the other direction before doing so. It may seem given the number of other features I’m adding that ‘show pure deletion conflicts’ is small potatoes, but version control systems are important and feature decisions shouldn’t be made in them without serious analysis.

1

It can even cleanly merge together two different people applying the exact same conflict resolution independently of each other, at least most of the time. An exception is if one person goes AE → ABDE → ABCDE and someone else goes AE → ACE → ABCDE then the system will of necessity think the two C lines are different and make a result including both of them, probably as A>BCD>BCD|E. It isn’t possible to avoid this behavior without giving up eventual consistency, but it’s arguably the best option under the circumstances anyway. If both sides made their changes as part of a single patch this can be made to always merge cleanly.

2

The cases are that a line which appears in the child appears in both parents, just the left, just the right, or neither. That last one happens in the uncommon but important criss-cross case. One thing I still feel good about is that conflict markers should be lines saying ‘This is part of a conflict section, the section below this came from X’ where X is either local, remote, or neither, and there’s another special annotation for ‘this is the end of a conflict section’.

3

While it’s clear that a line which came from Alice but no other parent and a line which came from Bob but no other parent should be in conflict when immediately next to each other it’s much less clear whether a line which came from both Alice and Carol but not Bob should conflict with a line which came from Bob and Carol but not Alice. If that should be presented as ‘not a conflict’ then if the next line came from David but nobody else it isn’t clear how far back the non-David side of that conflict should be marked as starting.

Posted Tue Apr 29 04:39:25 2025 Tags:
Looking at what's happening, and analyzing rationales. #nist #iso #deployment #performance #security
Posted Wed Apr 23 22:40:28 2025 Tags:

Computer tools for providing commentary on Chess games are currently awful. People play over games using Stockfish, which is a useful but not terribly relevant tool, and use that as a guide for their own commentary. There are Chess Youtubers who are aren’t strong players and it’s obvious to someone even of my own mediocre playing strength (1700 on a good day) that they don’t know what they’re talking about because in many situations there’s the obvious best move which fails due to some insane computer line but they don’t even cover it because the computer thinks it’s clearly inferior. Presumably commentary I generated using Stockfish as a guide would be equally obvious to someone of a stronger playing strength than me. People have been talking about using computers to make automated commentary on Chess positions since computers started getting good at Chess, and the amount of progress made has been pathetic. I’m now going to suggest a tool which would be a good first step in that process, although it still requires a human to put together the color commentary. It would also be a fun AI project on its own merits, and possibly have a darker use which I’ll get to at the end.

There’s only one truly objective metric of how good a Chess position is, and that’s whether it’s a win, loss, or draw with perfect play. In a lost position all moves are equally bad. In a won position any move no matter how ridiculous which preserves the theoretical win is equally good. Chess commentary which was based off this sort of analysis would be insane. Most high level games would be a theoretical draw until some point deep into already lost for a human territory at which point some uninteresting move would be labeled the losing blunder because it missed out on some way of theoretically eking out a draw. Obviously such commentary wouldn’t be useful. But commentary from Stockfish isn’t much better. Stockfish commentary is how a roughly 3000 rated player feels about the position if it assumes it’s playing against an opponent of roughly equal strength. That’s a super specific type of player and not one terribly relevant to how humans might fare in a given position. It’s close enough to perfect that a lot of the aforementioned ridiculousness shows up. There are many exciting tactical positions which are ‘only’ fifteen moves or so from being done and the engine says ‘ho hum, nothing to see here, I worked it out and it’s a dead draw’. What we need for Chess commentary is a tool geared towards human play, which says something about human games.

Thanks for reading Bram’s Thoughts! Subscribe for free to receive new posts and support my work.

Here’s an idea of what to build: Make an AI engine which gets inputs of position, is told the ratings of the two players, the time controls, and the time left, and gives probabilities for a win, loss, or draw. This could be trained by taking a corpus of real human games and optimizing for Brier score. Without any lookahead this approach is limited by how strong of an evaluation it can get to, but that isn’t relevant for most people. Current engines at one node are probably around 2500 or so, so it might peter out in usefulness for strong grandmaster play, but you have my permission to throw in full Stockfish evaluations as another input when writing game commentary. The limited set of human games might hurt its overall playing strength, but throwing in a bunch of engine games for training or starting with an existing one node network is likely to help a lot. That last one in particular should save a lot of training time.

For further useful information you could train a neural network on the same corpus of games to predict the probability that a player will make each of the available legal moves based on their rating and the amount of time they spend making their move. Maybe the amount of time the opponent spent making their previous move should be included as well.

With all the above information it would be easy to make useful human commentary like ‘The obvious move here is X but that’s a bad idea because of line Y which even strong players are unlikely to see’. Or ‘This position is an objective win but it’s very tricky with very little time left on the clock’. The necessary information to make those observations is available, even if writing the color commentary is a whole other layer. Maybe an LLM could be trained to do that. It may help a lot for the LLM to be able to ask for evaluations of follow-on moves.

What all the above is missing is the ability to give any useful commentary on positional themes going on in games. Baby steps. Having any of the above would be a huge improvement in the state of the art. The insight that commentary needs to take into account what different skill levels and time controls think of the situation will remain an essential one moving forward.

What I’d really like to see out of the above is better Chess instruction. There are religious wars constantly going on about what the best practical advice for lower rated players is, and the truth is we simply don’t know. When people collect data from games they come up with results like by far the best opening for lower rated players as black is the Caro-Kann, which might or might not be true but indicates that the advice given to lower rated players based on what’s theoretically best is more than a little bit dodgy.

A darker use of the above would be to make a nearly undetectable cheating engine. With the addition of it giving an output of the range of likely amounts of time the player is likely to take in a given position it could make an indistinguishable facsimile of a player of a given playing strength in real time whose only distinguishing feature is being a bit too typical/generic, and that would be easy enough to throw in bias for. In situations where it wanted to plausibly win a game against a much higher opponent it could filter out potential moves based on their practical chances in the given situation being bad. That would result in very non-Stockfish-like play and seemingly a player plausibly of that skill level happening to play particularly well that game. Good luck coming up with anti-cheat algorithms to detect that.

Thanks for reading Bram’s Thoughts! Subscribe for free to receive new posts and support my work.

Posted Sun Apr 20 04:09:03 2025 Tags:

There are two different goals of Chess AI: To figure out what is objectively the very best move in each situation, and to figure out what is, for me as a human, the best way to play in each situation. And possibly explain why. The explanations part I have no good ideas for short of doing an extraordinary amount of manual work to make a training set but the others can be done in a fairly automated manner.

(As with all AI posts everything I say here is speculative, may be wrong, and may be reinventing known techniques, but has reasonable justifications about why it might be a good idea.)

Thanks for reading Bram’s Thoughts! Subscribe for free to receive new posts and support my work.

First a controversial high level opinion which saves a whole lot of computational power: There is zero reason to try to train an AI on deep evaluations of positions. Alpha-beta pruning works equally well for all evaluation algorithms. Tactics are tactics. What training should do is optimize for immediate accuracy on a zero node eval. What deep evaluation is good for is generating more accurate numbers to go into the training data. For a real engine you as want switching information to say which moves should be evaluated more deeply by the alpha-beta pruner. For that information I’m going to assume that when doing a deep alpha-beta search you can get information about how critical each branch is and that can be used as a training set. I’m going to hand wave and assume that there’s a reasonable way of making that be the output of an alpha-beta search even though I don’t know how to do it.

Switching gears for a moment, there’s something I really want but doesn’t seem to exist: An evaluation function which doesn’t say what the best move for a godlike computer program is, but one which says what’s the best practical move for me, a human being, to make in this situation. Thankfully that can be generated straightforwardly if you have the right data set. Specifically, you need a huge corpus of games played by humans and the ratings of the players involved. You then train an AI with input of the ratings of the players and the current position and it returns probability of win/loss/draw. This is something people would pay real money for access to and can be generated from an otherwise fairly worthless corpus of human games. You could even get fancy and customize it a bit to a particular player’s style if you have enough games from them, but that’s a bit tricky because each human generates very few games and you’d have to somehow relate them to other players by style to get any real signal.

Back to making not a human player but a godlike player. Let’s say you’re making something like Leela, with lots of volunteer computers running tasks to improve it. As is often the case with these sorts of things the bottleneck seems to be bandwidth. To improve a model you need to send a copy of it to all the workers, have them locally generate suggested improvements to all the weights, then send those back. That requires a complete upload and download of the model from each worker. Bandwidth costs can be reduced either by making generations take longer or by making the model smaller. My guess is that biasing more towards making the model smaller is likely to get better results due to the dramatically improved training and lower computational overhead and hence deeper searches when using it in practice.

To make suggestions on how to improve a model a worker does as follows: First, they download the last model. Then they generate a self-play game with it. After each move of the game they take the evaluation which the deeper look-ahead gave and train the no look-ahead eval against that to update their suggestions for weight updates. Once it’s time for the next generation they upload all their suggested updates to the central server which sums all the weight updates suggestions (possibly weighting them by the amount of games which went into them) and uses that for the next generation model.

This approach shows how chess is in some sense an ‘easy’ problem for AI because you don’t need training data for it. You can generate all the training data you want out of thin air on an as needed basis.

Obviously there are security issues here if any of the workers are adversarial but I’m not sure what the best way to deal with those is.

Thanks for reading Bram’s Thoughts! Subscribe for free to receive new posts and support my work.

Posted Sun Mar 30 02:15:12 2025 Tags:

There are numerous videos reviewing 3D printer filaments to help you determine which is the best. I’ve spent way too much time watching these and running over data and can quickly summarize all the information relevant to most people doing 3D printing: Use PLA. There, you’re finished. If you want or need more information or are interested in running tests yourself read on.

There are two big components of the ‘strength’ of a material: stiffness and toughness. Stiffness refers to how hard it is to bend (or stretch/break) while toughness refers to how well it recovers from being bent (or stretched). These can be further broken down into subcategories, like whether the material successfully snaps back after getting bent or is permanently deformed. An important thing to understand is that the measures used aren’t deep ethereal properties of material, they’re benchmark numbers based on what happens if you run particular tests. This isn’t a problem with the tests, it’s an acknowledgement of how complex real materials are.

Thanks for reading Bram’s Thoughts! Subscribe for free to receive new posts and support my work.

For the vast majority of 3D printing projects what you care about is stiffness rather than toughness. If your model is breaking then most of the time the solution is to engineer it to not bend that much in the first place. The disappointing thing is that PLA has very good stiffness, usually better even than the exotic filaments people like experimenting with. In principle proper annealing can get you better stiffness, but when doing that you wind up reinventing injection molding badly and it turns out the best material for that is also PLA. The supposedly better benchmarks of PLA+ are universally tradeoffs where they get better toughness in exchange for worse stiffness. PLA is brittle, so it shatters on failure, and mixing it with any random gunk tends to make that tradeoff, but it isn’t what you actually want.

(If you happen to have an application where your material bending or impact resistance is important you should consider TPU. The tradeoffs of different versions of that are complex and I don’t have any experience with it so can’t offer much detailed advice.)

Given all the above, plus PLA’s generally nontoxic and easy to print nature, it’s the go-to filament for the vast majority of 3D printing applications. But let’s say you need something ‘better’, or are trying to justify the ridiculous amounts of time you’ve spent researching this subject, what is there to use? The starting place is PLA’s weaknesses: It gets destroyed by sunlight, can’t handle exposure to many corrosive chemicals, and melts at such a low temperature that it can be destroyed in a hot car or a sauna. There are a lot of fancy filaments which do better on these benchmarks, but for the vast majority of things PLA isn’t quite good enough at PETG would fit the bill. The problem with PETG is that it isn’t very stiff. But in principle adding carbon fiber fixes this problem. So, does it?

There are two components of stiffness for 3d printing: Layer adhesion and bending modulus. Usually layer adhesion issues can be fixed by printing in the correct orientation, or sometimes printing in multiple pieces at appropriate orientations. One could argue that the answer ‘you can engineer around that’ is a cop-out but in this cases the effect is so extreme that it can’t be ignored. More on this below, but my test is of bending modulus.

Now that I’ve finished an overly long justification of why I’m doing bending modulus tests we can get to the tests themselves. You can get the models I used for the tests over here. The basic idea is to make a long thin bar in the material to be tested, hang a weight from the middle, and see how much it bends. Here are the results:

CarbonX PETG-CF is a great stronger material, especially if you want/need something light weight spindly. It’s considerably more expensive than PLA but cheaper and easier to print than fancier materials and compared to PLA and especially PETG the effective cost is much less because you need less of it. The Flashforge PETG-CF (which is my stand-in ‘generic’ PETG-CF as it’s what turns up in an Amazon search) is a great solution if you want something with about the same price and characteristics as PLA but better able to handle high temperatures and sunlight. It’s so close to PLA that I’m suspicious that it’s actually just a mislabeled roll of PLA but I haven’t tested that. I don’t know why the Bambu PETG-CF performed so badly. It’s possibly it got damaged by moisture between when I got it and tested it but I tried drying it thoroughly and that didn’t help.

Clearly not all carbon fiber filaments are the same and more thorough testing should be done with a setup less janky than mine. If anybody wants to use my models as a starting point for that please go ahead.

The big caveat here is that you can engineer around a bad bending modulus. The force needed to bend a beam goes up with the cube of its width, so unless something has very confined dimensions you can make it much stronger by making it chunkier. You can do it without using all that much more material by making I-beam like structures. Note that when 3D printing you can make enclosed areas no problem so the equivalent of an I-beam should have a square, triangular, or circular cross section with a hollow middle. The angle of printing is also of course very important.

The conclusion is that if you want something more robust than PLA you can use generic PETG engineered to be very chunky, or PETG-CF with appropriate tradeoffs between price and strength for your application.

A safety warning: Be careful to ventilate your space thoroughly when printing carbon fiber filaments, and don’t shred or machine them after printing. Carbon fiber has the same ill effects on lungs as asbestos so you don’t want to be breathing it in. In my tests the amount of volatile organic compounds produced are small, but it’s a good idea to be careful.

Thanks for reading Bram’s Thoughts! Subscribe for free to receive new posts and support my work.

Posted Sun Mar 23 21:16:26 2025 Tags:

An Update Regarding the 2025 Open Source Initiative Elections

I've explained in other posts that I ran for the 2025 Open Source Initative Board of Directors in the “Affiliate” district.

Voting closed on MON 2025-03-17 at 10:00 US/Pacific. One hour later, candidates were surprised to receive an email from OSI demanding that all candidates sign a Board agreement before results were posted. This was surprising because during mandatory orientation, candidates were told the opposite: that a Board agreement need not be signed until the Board formally appointed you as a Director (as the elections are only advisory &mdash: OSI's Board need not follow election results in any event. It was also surprising because the deadline was a mere 47 hours later (WED 2025-03-19 at 10:00 US/Pacific).

Many of us candidates attempted to get clarification over the last 46 hours, but OSI has not communicated clear answers in response to those requests. Based on these unclear responses, the best we can surmise is that OSI intends to modify the ballots cast by Affiliates and Members to remove any candidate who misses this new deadline. We are loathe to assume the worst, but there's little choice given the confusing responses and surprising change in requirements and deadlines.

So, I decided to sign a Board Agreement with OSI. Here is the PDF that I just submitted to the OSI. I emailed it to OSI instead. OSI did recommend DocuSign, but I refuse to use proprietary software for my FOSS volunteer work on moral and ethical grounds0 (see my two keynotes (FOSDEM 2019, FOSDEM 2020) (co-presented with Karen Sandler) on this subject for more info on that).

My running mate on the Shared Platform for OSI Reform, Richard Fontana, also signed a Board Agreement with OSI before the deadline as well.


0 Chad Whitacre has made unfair criticism of my refusal tog use Docusign as part of the (apparently ongoing?) 2025 OSI Board election political campaign. I respond to his comment here in this footnote (& further discussion is welcome using the fediverse, AGPLv3-powered comment feature of my blog). I've put it in this footnote because Chad is not actually raising an issue about this blog post's primary content, but instead attempting to reopen the debate about Item 4 in the Shared Platform for OSI Reform. My response follows:

In addition to the two keynotes mentioned above, I propose these analogies that really are apt to this situation:

  • Imagine if the Board of The Nature Conservancy told Directors they would be required, if elected, to use a car service to attend Board meetings. It's easier, they argue, if everyone uses the same service and that way, we know you're on your way, and we pay a group rate anyway. Some candidates for open Board seats retort that's not environmentally sound, and insist — not even that other Board members must stop using the car service &mdash: but just that Directors who chose should be allowed to simply take public transit to the Board meeting — even though it might make them about five minutes late to the meeting. Are these Director candidates engaged in “passive-aggressive politicking”?
  • Imagine if the Board of Friends of Trees made a decision that all paperwork for the organization be printed on non-recycled paper made from freshly cut tree wood pulp. That paper is easier to move around, they say — and it's easier to read what's printed because of its quality. Some candidates for open Board seats run on a platform that says Board members should be allowed to get their print-outs on 100% post-consumer recycled paper for Board meetings. These candidates don't insist that other Board members use the same paper, so, if these new Directors are seated, this will create extra work for staff because now they have to do two sets of print-outs to prep for Board meetings, and refill the machine with different paper in-between. Are these new Director candidates, when they speak up about why this position is important to them as a moral issue, a “a distracting waste of time”?
  • Imagine if the Board of the APSCA made the decision that Directors must work through lunch, and the majority of the Directors vote that they'll get delivery from a restaurant that serves no vegan food whatsoever. Is it reasonable for this to be a non-negotiable requirement — such that the other Directors must work through lunch and just stay hungry? Or should they add a second restaurant option for the minority? After all, the ASPCA condemns animal cruelty but doesn't go so far as to demand that everyone also be a vegan. Would the meat-eating directors then say something like “opposing cruelty to animals could be so much more than merely being vegan” to these other Directors?
Posted Wed Mar 19 08:59:00 2025 Tags:

An Update Regarding the 2025 Open Source Initiative Elections

I've explained in other posts that I ran for the 2025 Open Source Initative Board of Directors in the “Affiliate” district.

Voting closed on Monday 2025-03-17 at 10:00 US/Pacific. One hour after that, I and at least three other candidates received the following email:

Date: Mon, 17 Mar 2025 11:01:22 -0700
From: OSI Elections team <elections@opensource.org>
To: Bradley Kuhn <bkuhn@ebb.org>
Subject: TIME SENSITIVE: sign OSI board agreement
Message-ID: <civicrm_67d86372f1bb30.98322993@opensource.org>

Thanks for participating in the OSI community polls which are now closed. Your name was proposed by community members as a candidate for the OSI board of directors. Functioning of the board of directors is critically dependent on all the directors committing to collaborative practices.

For your name to be considered by the board as we compute and review the outcomes of the polls,you must sign the board agreement before Wednesday March 19, 2025 at 1700 UTC (check times in your timezone). You’ll receive another email with the link to the agreement.

TIME SENSITIVE AND IMPORTANT: this is a hard deadline.

Please return the signed agreement asap, don’t wait. 

Thanks

OSI Elections team

(The link email did arrived too, with a link to a proprietary service called DocuSign. Fontana downloaded the PDF out of DocuSign and it appears to match the document found here. This document includes a clause that Fontana and I explicitly indicated in our OSI Reform Platform should be rewritten. )

All the (non-incumbent) candidates are surprised by this. OSI told us during the mandatory orientation meetings (on WED 2025-02-19 & again on TUE 2025-02-25) that the Board Agreement needed to be signed only by the election winners who were seated as Directors. No one mentioned (before or after the election) that all candidates, regardless of whether they won or lost, needed to sign the agreement. I've also served o many other 501(c)(3) Boards, and I've never before been asked to sign anything official for service until I was formally offered the seat.

Can someone more familiar with the OSI election process explain this? Specifically, why are all candidates (even those who lose) required to sign the Board Agreement before election results are published? Can folks who ran before confirm for us that this seems to vary from procedures in past years? Please reply on the fediverse thread if you have information. Richard Fontana also reached out to OSI on their discussion board on the same matter.

Posted Mon Mar 17 20:26:00 2025 Tags: