Not Even Wrong.

宝贝开心网There is a conceptual division of statements of fact that places them on a sort of spectrum from “right” to “wrong”. Right facts are those that square with what is observed in the world (e.g. “water is wet”) and wrong ideas are those that do not (e.g. “water is pink”). Inherent in this is the idea of falsifiablity: these statements assert facts, and the truth or falsity of these facts can be determined. Statements that are not even wrong are those that do not engage with the mechanisms of meaning, truth, and so forth, and so cannot be tested (e.g. “water is beautiful”). Some people may find a particular body of water beautiful or not, on a given day, but that says more about the people than the water, and is not something that can really be falsified.

宝贝开心网Aeon published a fairly regrettable article, called “The Empty Brain“, which, despite the almost self-aware title, does not appear to be an autobiography. It’s main problem is that the author is not aware of the meaning of the words he uses, and so from possibly correct, or at least coherent premises, builds an Escher-esque house of failed conclusions.

No matter how hard they try, brain scientists and cognitivepsychologists will never find a copy of Beethoven’s 5th Symphony in thebrain – or copies of words, pictures, grammatical rules or any otherkinds of environmental stimuli. The human brain isn’t really empty, ofcourse. But it does not contain most of the things people think it does – not even simple things such as ‘memories’.

This is, of course, wrong. The brain is, in fact, the organ of the body in which memories are stored. This has been demonstrated, both in research on animals and in unfortunate cases where humans sustained trauma to the brain and lost memories, or memory-related functions, as a consequence. Anyone asserting otherwise would have to find an organ which stores memories, and is not the brain. This approach, of asserting that something is not the case, but failing to indicate what is, appears to be Epstein’s primary mode of argument.

He is somewhat correct, in that the brain does not contain copies of the listed items in a form that you can simply peer into the brain and read back out. The idea that they are not stored at all, however, begs the question of how we operate using something that Epstein asserts that we do not have, and worse, how we have the subjective experience of having something he asserts we don’t have.

Ourshoddy thinking about the brain has deep historical roots, but the invention of computers in the 1940s got us especially confused. For morethan half a century now, psychologists, linguists, neuroscientists andother experts on human behaviour have been asserting that the humanbrain works like a computer.

People have used a number of metaphors to explain the working of a number of systems. The brain/computer one is flawed, and in some places strained, but at a very high level has some explanatory value. The problems mostly arise when people mistake the map for the territory. In later paragraphs, Epstein does this on a level roughly on par with seeing a map of the United States, and then asserting that one could jump across the United States, since it’s only about a meter wide.

To see how vacuous this idea is,consider the brains of babies. Thanks to evolution, human neonates, likethe newborns of all other mammalian species, enter the world preparedto interact with it effectively. A baby’s vision is blurry, but it paysspecial attention to faces, and is quickly able to identify itsmother’s. It prefers the sound of voices to non-speech sounds, and candistinguish one basic speech sound from another. We are, without doubt,built to make social connections.

A healthy newborn is alsoequipped with more than a dozen reflexes – ready-made reactions tocertain stimuli that are important for its survival. It turns its headin the direction of something that brushes its cheek and then suckswhatever enters its mouth. It holds its breath when submerged in water.It grasps things placed in its hands so strongly it can nearly supportits own weight. Perhaps most important, newborns come equipped withpowerful learning mechanisms that allow them to change rapidlyso they can interact increasingly effectively with their world, even ifthat world is unlike the one their distant ancestors faced.

So far so good, these statements about the behavior of newborn babies are largely correct. They have a vast number of built-in capabilities, which are part of their structure, as described by their DNA and built in utero according to that plan.

Senses,reflexes and learning mechanisms – this is what we start with, and itis quite a lot, when you think about it. If we lacked any of thesecapabilities at birth, we would probably have trouble surviving.

But here is what we are not born with: information,data, rules, software, knowledge, lexicons, representations,algorithms, programs, models, memories, images, processors, subroutines,encoders, decoders, symbols, or buffers – design elements that allow digital computers to behave somewhat intelligently. Not only are we not born with such things, we also don’t develop them – ever.

And here is where we run up against the limitations of Epstein’s knowledge and lexicon. These words mean things, and many of them mean things that are exactly what we do develop. Information, for example, is, at a very basic and informal level, the ability to discriminate between things. It has an inverse, called entropy. In the game of 20 Questions, the guessing player starts off with no information except that the answering player is thinking of a thing. Each question they ask adds one bit of information, and causes a corresponding reduction in their entropy. To assert that humans never “develop” information is to assert that humans never acquire the ability to tell anything from anything else, and so experience the world as a sort of colossal monolith of all things.

An algorithm is a procedure for solving a problem or doing a calculation. If you ever learned to do long division, change a car tire, or get dressed, you have an algorithm, and if you really sat down and thought about it, you could probably write the procedure down. If you never learned to do any of that stuff, you’re naked and walking everywhere, so you’re really not my problem.

Mixed in with the things that we clearly do develop are some that we clearly don’t. To say that the brain has “software”, for example, strains the metaphor to the breaking point. Yes, one could make a distinction between the activity of the brain and the physical matter of the brain, but since the matter does the activity and the activity changes the matter, the distinction isn’t terribly useful except when considering the possibility of executing the activity in simulation, on different matter.

We don’t store words or the rules that tell us how to manipulate them. We don’t create representations of visual stimuli, store them in a short-term memory buffer, and then transfer the representation into a long-term memory device. We don’t retrieve information or images or words from memory registers. Computers do all of these things, but organisms do not.

Computers, quite literally, process information– numbers, letters, words, formulas, images. The information first hasto be encoded into a format computers can use, which means patterns ofones and zeroes (‘bits’) organised into small chunks (‘bytes’). On mycomputer, each byte contains 8 bits, and a certain pattern of those bitsstands for the letter d, another for the letter o, and another for the letter g. Side by side, those three bytes form the word dog.One single image – say, the photograph of my cat Henry on my desktop –is represented by a very specific pattern of a million of these bytes(‘one megabyte’), surrounded by some special characters that tell thecomputer to expect an image, not a word.

This is where Epstein starts to lose the plot with regard to what information is. Information is not just numbers, letters, words and so forth. It is the ability to discriminate. One bit, the fundamental unit of information, has two possible values, typically represented as 1 and 0. It allows a single discrimination, this/that, here/there, etc. Unfortunately for this line of argument, that’s pretty much all that a bit is. The fact that computers happen to handle the bits as chunks of 8 to a byte, or that certain patterns stand for certain things are what’s called “implementation details”.

Paul Revere’s friend in the Old North Church on the eve of the revolution sent a two-bit message to Paul using lanterns. The famous line is “One if by land, two if by sea”, with the number of lanterns indicating the approach direction of the British forces. This could be done by one bit: 1 lantern for land, 0 lanterns for sea. However, there was a second bit needed to distinguish a potential failure case: 11 (binary for 2) if by sea, 01 (binary for one) if by land, 00 (binary for 0) if they catch you before you put the lantern up. Note that these cases have nothing to do with computers, because Paul’s cell phone was unreliable or something.

The fact that we don’t store our visual memories in our heads as 1024×768 pixel 24-bit per pixel JPG-compressed image files doesn’t mean we don’t have representations, just that they’re not the same as the ones in computers. There is still latent information, but the implementation details are different.

Computers, quite literally, move these patterns from place to place in different physicalstorage areas etched into electronic components. Sometimes they alsocopy the patterns, and sometimes they transform them in various ways –say, when we are correcting errors in a manuscript or when we aretouching up a photograph. The rules computers follow for moving, copyingand operating on these arrays of data are also stored inside thecomputer. Together, a set of rules is called a ‘program’ or an‘algorithm’. A group of algorithms that work together to help us dosomething (like buy stocks or find a date online) is called an‘application’ – what most people now call an ‘app’.

Yes, the way a computer does these things is called an algorithm. This is a matter of convention, though. The way I make a cake is also an algorithm, and while accurate, it would sound stilted for me to say it that way, so I don’t. That doesn’t make it less correct, though.

Forgive me for this introduction to computing, but I need to be clear: computers really do operate on symbolic representations of the world. They really store and retrieve. They really process. They really have physical memories. They really are guided in everything they do, without exception, by algorithms.

Humans,on the other hand, do not – never did, never will. Given this reality,why do so many scientists talk about our mental life as if we werecomputers?

Again with the asserting that things are not, without proposing what they are. If human memories are not physical, then what are they? If we don’t do things by following procedures, then how do we do them?

In his book In Our Own Image(2015), the artificial intelligence expert George Zarkadakis describessix different metaphors people have employed over the past 2,000 yearsto try to explain human intelligence.

In the earliest one, eventually preserved in the Bible, humans were formed from clay or dirt, which an intelligent god then infused with its spirit. That spirit‘explained’ our intelligence – grammatically, at least.

Theinvention of hydraulic engineering in the 3rd century BCE led to thepopularity of a hydraulic model of human intelligence, the idea that theflow of different fluids in the body – the ‘humours’ – accounted forboth our physical and mental functioning. The hydraulic metaphorpersisted for more than 1,600 years, handicapping medical practice allthe while.

By the 1500s, automata powered by springs and gears had been devised, eventually inspiring leading thinkers such as René Descartes to assert that humans are complex machines. In the 1600s, the British philosopher Thomas Hobbes suggested that thinking arose from small mechanical motions in the brain. By the 1700s, discoveries about electricity and chemistry led to new theories of human intelligence –again, largely metaphorical in nature. In the mid-1800s, inspired by recent advances in communications, the German physicist Hermann von Helmholtz compared the brain to a telegraph.

Eachmetaphor reflected the most advanced thinking of the era that spawnedit. Predictably, just a few years after the dawn of computer technologyin the 1940s, the brain was said to operate like a computer, with therole of physical hardware played by the brain itself and our thoughtsserving as software. The landmark event that launched what is nowbroadly called ‘cognitive science’ was the publication of Language and Communication(1951) by the psychologist George Miller. Miller proposed that themental world could be studied rigorously using concepts from informationtheory, computation and linguistics.

The key word of this is “metaphor”. The metaphor that the brain is like a computer indicates that at some level it shares some properties, not that the brain and a computer are identical. If I say my girlfriend’s cheeks are like roses, I mean that they are pink and soft, not that she literally has flowers for a face.

Information theory is the basis of all the talk about entropy and bits earlier, it is the study of systems capable of discrimination, as humans appear to be, between the things in their environments, so it doesn’t seem like too much of a stretch to attempt to apply it to the question of how we do that discriminating.

This kind of thinking was taken to its ultimate expression in the short book The Computer and the Brain (1958), in which the mathematician John von Neumann stated flatly that the function of the human nervous system is ‘prima faciedigital’. Although he acknowledged that little was actually known about the role the brain played in human reasoning and memory, he drew parallel after parallel between the components of the computing machines of the day and the components of the human brain.

Propelled bysubsequent advances in both computer technology and brain research, anambitious multidisciplinary effort to understand human intelligencegradually developed, firmly rooted in the idea that humans are, likecomputers, information processors. This effort now involves thousands ofresearchers, consumes billions of dollars in funding, and has generateda vast literature consisting of both technical and mainstream articlesand books. Ray Kurzweil’s book How to Create a Mind: The Secret of Human Thought Revealed(2013), exemplifies this perspective, speculating about the‘algorithms’ of the brain, how the brain ‘processes data’, and even howit superficially resembles integrated circuits in its structure.

Von Neumann’s assertion that the activity of the nervous system is digital is based on the observation of the electrical activity of nerves, which appear to have two states: resting and firing, and change the rate at which they fire, rather than e.g. the amplitude with which they fire. Note again, the appearance of the word two, that is to say, one bit of information, firing/resting. Whether sub-threshold activity, which does not tip the neuron into firing, has a place in cognition is an open research question. The point is that Von Neumann did not mean that everyone was running around with a ENIAC full of vacuum tubes in their head, but that the activity of neurons appeared to be divided into two phases, rather than a continuum. Digital, not analog.

Having not read the Kurtzweil book, I cannot speak to its content or the accuracy of the review. However, anyone with any knowledge of the structure, at the IC level in computers or the neuronal level in brains, would regard any similarity as purely superficial: they’re both really complicated.

The idea that humans are information processors is, with a proper understanding of what information is, fairly trivial to assert. Anything that reacts to its environment is an information processor at some level, as it has received information (that is, it has determined that some condition holds or not) and then engaged in some process using that information.

Theinformation processing (IP) metaphor of human intelligence nowdominates human thinking, both on the street and in the sciences. Thereis virtually no form of discourse about intelligent human behaviour thatproceeds without employing this metaphor, just as no form of discourseabout intelligent human behaviour could proceed in certain eras andcultures without reference to a spirit or deity. The validity of the IPmetaphor in today’s world is generally assumed without question.

Butthe IP metaphor is, after all, just another metaphor – a story we tellto make sense of something we don’t actually understand. And like allthe metaphors that preceded it, it will certainly be cast aside at somepoint – either replaced by another metaphor or, in the end, replaced byactual knowledge.

At the beginning of this article, if you can really call it that, the author asserted that humans don’t develop knowledge.Now he says we’ll replace our metaphors with knowledge. As to the validity of the current metaphor, it has its good points and its bad ones, but the main problem is in over-applying it, or insisting that it holds true in cases where it doesn’t. The idea that we can follow a sequence of steps to perform a task (that is, use an algorithm) seems to have been extended (at least by Epstein) to mean that we run a bootleg copy of Windows in our heads. The idea that there is a representation stored in our brains has been overextended (again, by Epstein) to mean that we store the image file “mom.png” in a folder someplace. Unfortunately for the line of argument against these over-extensions, no one actually believes that.That’s the whole point of a metaphor. It’s not literally true, it just says there exist similarities.

Just over a year ago, on a visit to one of theworld’s most prestigious research institutes, I challenged researchersthere to account for intelligent human behaviour without reference toany aspect of the IP metaphor. They couldn’t do it, and when Ipolitely raised the issue in subsequent email communications, they stillhad nothing to offer months later. They saw the problem. They didn’tdismiss the challenge as trivial. But they couldn’t offer analternative. In other words, the IP metaphor is ‘sticky’. It encumbersour thinking with language and ideas that are so powerful we havetrouble thinking around them.

Now this is a legitimate problem, and an interesting challenge. All maps are wrong, but some maps are useful, and the IP map certainly has some utility. However, having it as the only map you can use to think about something limits the thinking you can do.

The faulty logic of the IP metaphoris easy enough to state. It is based on a faulty syllogism – one withtwo reasonable premises and a faulty conclusion. Reasonable premise #1: all computers are capable of behaving intelligently. Reasonable premise #2: all computers are information processors. Faulty conclusion: all entities that are capable of behaving intelligently are information processors.

Setting aside the formal language, the idea that humans must be information processors just because computersare information processors is just plain silly, and when, some day, theIP metaphor is finally abandoned, it will almost certainly be seen thatway by historians, just as we now view the hydraulic and mechanicalmetaphors to be silly.

After such a promising preceding paragraph, this descent into silly-gisms is a disappointment. Premise #1 is nothing like reasonable. No one who works with computers for any length of time is capable of thinking something like that without at least a wry smile, and sometimes a chuckle. Computers are stupid. They are literally dumb as rocks: their main active components are made of silicon, the main constituent of quartz. However, computers are also fast. They are capable of manipulating the symbols they work on at blazing speeds, and so they can do things that humans find hard (multiplying large numbers, looking through a list of a million names to see if a specific one is on it) easily. They are not, however, intelligent.

The loss of the premise gets rid of the syllogism, but perhaps its conclusion, while logically unsound, still has some merit. The terms are, admittedly, ill defined. Just what is “behaving intelligently”?

The portia genus of jumping spider eats other spiders, and has a repertoire of behaviors it uses to approach and attack other spiders. These include different ways of tapping on the webs of other spiders, to disguise its approach or to mimic trapped insects. If one of these approaches fails, it will try others, and can learn which ones are effective against which kinds of spiders. Portia also has the ability to make long detours that take it out of sight of prey,in order to descend on its prey from behind. These seem like intelligent behaviors, if fairly minimal ones.

However, in order to do all these things, portia receives and operates on information. It uses its eyes to distinguish between different kinds of prey spiders (again, discrimination is the basis of information). It uses some form of mental map-building and direction sensing to make its detours. So even this very basic intelligent behavior relies on information being accessed and used.

As a thought experiment, then, what intelligent behavior would be possible without performing some process on some information? With no information, there is no distinguishing between things, so the universe is perceived as a single confusion of sense-data, with no distinguishing characteristics (as those would be information), or not perceived at all (as something/nothing is exactly one bit of information). No behavior can be selected, either. Selection of one behavior, as opposed to another, gives rise to a single bit of information. So yes, all behavior, at some point, is a product of information being processed. One could point out that a rock might roll down a hill, receiving no input and selecting no output, but that is hardly “behavior” in any sense that the word is normally used, and it’s certainly not intelligent.

If the IP metaphor is so silly, why is itso sticky? What is stopping us from brushing it aside, just as we might brush aside a branch that was blocking our path? Is there a way tounderstand human intelligence without leaning on a flimsy intellectual crutch? And what price have we paid for leaning so heavily on thisparticular crutch for so long? The IP metaphor, after all, has beenguiding the writing and thinking of a large number of researchers inmultiple fields for decades. At what cost?

Ok, now we’re getting somewhere interesting again. The bit with the syllogism could have been left out, and would have strengthened the argument. Unfortunately, this is the last we’ll hear, in this essay at least, about this potentially fruitful line of inquiry.

In aclassroom exercise I have conducted many times over the years, I beginby recruiting a student to draw a detailed picture of a dollar bill –‘as detailed as possible’, I say – on the blackboard in front of theroom. When the student has finished, I cover the drawing with a sheet ofpaper, remove a dollar bill from my wallet, tape it to the board, andask the student to repeat the task. When he or she is done, I remove thecover from the first drawing, and the class comments on thedifferences.

Because you might never have seen a demonstrationlike this, or because you might have trouble imagining the outcome, Ihave asked Jinny Hyun, one of the student interns at the institute whereI conduct my research, to make the two drawings. Here is her drawing‘from memory’ (notice the metaphor):

宝贝开心网

And here is the drawing she subsequently made with a dollar bill present:

Jinnywas as surprised by the outcome as you probably are, but it is typical.As you can see, the drawing made in the absence of the dollar bill ishorrible compared with the drawing made from an exemplar, even thoughJinny has seen a dollar bill thousands of times.

What is theproblem? Don’t we have a ‘representation’ of the dollar bill ‘stored’ ina ‘memory register’ in our brains? Can’t we just ‘retrieve’ it and useit to make our drawing?

This is the problem with the metaphor leading us into a variety of possible traps in how we think about things. The first is that since humans do have memories (despite Epstein’s assertions to the contrary) and computers have memories (RAM is “Random Access Memory” after all), they must be exactly the same objects. This is, when stated clearly, obviously wrong. Humans have existed far longer than computers, and that is a useful clue to the source of the confusion. The memory in computers was named that by analogy to the function of our memory: it is a place to store some form of representation. Computer memories are precise where ours our somewhat fuzzy, delicate where ours are surprisingly robust, and made of silicon metal and plastic where ours are made mostly out of wet fat. The analogy is at a functional level, not the details of implementation.

Obviously not, and a thousand years ofneuroscience will never locate a representation of a dollar bill storedinside the human brain for the simple reason that it is not there to befound.

Wait, what? Then how did his student call up anything at all? The term “dollar bill” refers to something, and it’s something most Americans are familiar with. If there was nothing in Jinny’s brain that in some way represented a dollar bill, then when she was asked to draw one, she would have said something like “What is a ‘dollar bill’?” The term would not have referred to anything, and since it wasn’t likely to refer to a particular actual dollar bill (Jinny probably doesn’t keep her money between her ears), it would refer to some representation of one.

But for now, lets take Epstein at (pardon the pun) face value. There are no representations of anything in the brain.

A wealth of brain studies tells us, in fact, that multiple and sometimes large areasof the brain are often involved in even the most mundane memory tasks.When strong emotions are involved, millions of neurons can become moreactive. In a 2016 studyof survivors of a plane crash by the University of Torontoneuropsychologist Brian Levine and others, recalling the crash increasedneural activity in ‘the amygdala, medial temporal lobe, anterior andposterior midline, and visual cortex’ of the passengers.

This part is actually pretty accurate. Even more interestingly, the storage is somehow holographic, in the sense that it requires pretty widespread damage to remove memories, rather than having them highly localized, and so lost with minor damage.

The idea, advanced by several scientists, that specific memories are somehow stored in individual neuronsis preposterous; if anything, that assertion just pushes the problem ofmemory to an even more challenging level: how and where, after all, isthe memory stored in the cell?

I’m willing to take this as an axiom. It’s hard to propose a method for handling the storage, and it has weird implications. For example, infants are born with lots of neurons already in place, but haven’t experienced much, so what do their neurons store? White noise? The sound of one hand clapping?

I do, however, find it suspect that he was able to cite a lot of studies about multiple regions of the brain becoming active during memory tasks, but when it comes to this one-neuron-one-memory idea, suddenly it’s a murky “several scientists”. Which ones?

So what is occurring when Jinny draws the dollar bill in its absence? If Jinny had never seen a dollar bill before, her first drawing would probably have notresembled the second drawing at all. Having seen dollar bills before, she was changed in some way. Specifically, her brain was changed in a way that allowed her to visualise a dollar bill – that is, to re-experience seeing a dollar bill, at least to some extent.

Ok, so there is a change in her brain, which has at least some of the content of seeing a dollar bill, but is not a representation. This is either a distinction without a difference, or the author descending into near-incoherence. A representation is a description or portrayal, a set of signs that stand in for (that “represent”) something else. The changes to Jinny’s brain are not a dollar bill, clearly, but they stand in for it when she is asked to draw one. They’re just not very good or precise stand-ins, largely because they don’t need to be to permit Jinny to do things like recognize dollar bills when she is presented with them.

Thedifference between the two diagrams reminds us that visualisingsomething (that is, seeing something in its absence) is far less accurate than seeing something in its presence. This is why we’re muchbetter at recognising than recalling. When we re-member something (from the Latin re, ‘again’, and memorari,‘be mindful of’), we have to try to relive an experience; but when we recognise something, we must merely be conscious of the fact that wehave had this perceptual experience before.

Perhaps you willobject to this demonstration. Jinny had seen dollar bills before, butshe hadn’t made a deliberate effort to ‘memorise’ the details. Had she done so, you might argue, she could presumably have drawn the secondimage without the bill being present. Even in this case, though, no image of the dollar bill has in any sense been ‘stored’ in Jinny’s brain.She has simply become better prepared to draw it accurately, just as,through practice, a pianist becomes more skilled in playing a concertowithout somehow inhaling a copy of the sheet music.

I will admit that there is not a literal copy of a dollar bill in Jinny’s brain, in the sense that if you cracked the poor woman’s skull open and rooted around, you wouldn’t find anything you could pay a bar tab with. No one has ever made any claim that you would, though, so the point of this exercise is somewhat unclear. Clearly she’s undergoing an alteration that isnot the thing itself, but is something that stands in for the thing itself (i.e a representation). The fact that it’s not literally “dollar_bill.png” doesn’t mean the alteration didn’t happen.

Fromthis simple exercise, we can begin to build the framework of ametaphor-free theory of intelligent human behaviour – one in which thebrain isn’t completely empty, but is at least empty of the baggage of the IP metaphor.

Aswe navigate through the world, we are changed by a variety ofexperiences. Of special note are experiences of three types: (1) we observewhat is happening around us (other people behaving, sounds of music,instructions directed at us, words on pages, images on screens); (2) weare exposed to the pairing of unimportant stimuli (such as sirens) with important stimuli (such as the appearance of police cars); (3) we are punished or rewarded for behaving in certain ways.

Webecome more effective in our lives if we change in ways that areconsistent with these experiences – if we can now recite a poem or sing asong, if we are able to follow the instructions we are given, if werespond to the unimportant stimuli more like we do to the importantstimuli, if we refrain from behaving in ways that were punished, if webehave more frequently in ways that were rewarded.

Misleadingheadlines notwithstanding, no one really has the slightest idea how thebrain changes after we have learned to sing a song or recite a poem. Butneither the song nor the poem has been ‘stored’ in it. The brain hassimply changed in an orderly way that now allows us to sing thesong or recite the poem under certain conditions. When called on toperform, neither the song nor the poem is in any sense ‘retrieved’ fromanywhere in the brain, any more than my finger movements are ‘retrieved’when I tap my finger on my desk. We simply sing or recite – noretrieval necessary.

Except that the change to the brain is the storing of the memorized thing in it. It’s also a lot of other things, like the kinesthetics of the performance, the emotional content of it and the intonations and expressions that would convey that performance to others, and so on. The representation is different from the original, and possibly both richer and less accurate, but that’s a far cry from the assertion that no representations exist. They just are not precise copies.

A few years ago, I asked the neuroscientistEric Kandel of Columbia University – winner of a Nobel Prize foridentifying some of the chemical changes that take place in the neuronalsynapses of the Aplysia (a marine snail) after it learnssomething – how long he thought it would take us to understand how humanmemory works. He quickly replied: ‘A hundred years.’ I didn’t think toask him whether he thought the IP metaphor was slowing downneuroscience, but some neuroscientists are indeed beginning to think theunthinkable – that the metaphor is not indispensable.

A few cognitive scientists – notably Anthony Chemero of the University of Cincinnati, the author of Radical Embodied Cognitive Science(2009) – now completely reject the view that the human brain works likea computer. The mainstream view is that we, like computers, make senseof the world by performing computations on mental representations of it,but Chemero and others describe another way of understandingintelligent behaviour – as a direct interaction between organisms and their world.

I have only limited experience with neuroscience, but having done some computational neuroscience, rather than just talked to a neuroscientist once years ago, I can safely say that almost no one thinks that humans perform calculations (in the narrow sense that computers perform calculations, at least) on mental representations of the world.

On the other hand, I have fuckton of experience with robotics, and I can tell you that that approach to AI is called GOFAI (Good Old Fashioned AI), and it tends to run into combinatorial explosion problems when your world has more than like 12 things in it. It is not, in general, an effective way of dealing with a dynamic and changing world, especially in the absence of perfect perception. However, in narrow applications, it is terrifyingly effective. The last person who could play a computer to a stalemate in checkers died in the 70s, and since then, they have become perfect at it, in the formal sense. You, a human, cannot beat a computer at checkers.

This is the root of what’s known as Moravec’s paradox. The things that we literally do without thinking about it, like running across uneven ground, are absurdly difficult for computers, while things that we find tortuously brain-bending, like thinking a handful of moves ahead in chess, are easy for computers. Our brains are evolved to be good at certain things, and to do them efficiently and well enough to not die. We don’t need to explain these activities, because everyone who didn’t have how to acquire those skills hardwired into them from birth was eaten. The things that our brains did not evolve to be good at, like maintaining baroque and precise structures of abstractions and assessing them very quickly, computers happen to be very good at.

Myfavourite example of the dramatic difference between the IP perspectiveand what some now call the ‘anti-representational’ view of humanfunctioning involves two different ways of explaining how a baseballplayer manages to catch a fly ball – beautifully explicated by MichaelMcBeath, now at Arizona State University, and his colleagues in a 1995 paper in Science.The IP perspective requires the player to formulate an estimate ofvarious initial conditions of the ball’s flight – the force of theimpact, the angle of the trajectory, that kind of thing – then to createand analyse an internal model of the path along which the ball willlikely move, then to use that model to guide and adjust motor movementscontinuously in time in order to intercept the ball.

That is all well and good ifwe functioned as computers do, but McBeath and his colleagues gave asimpler account: to catch the ball, the player simply needs to keepmoving in a way that keeps the ball in a constant visual relationshipwith respect to home plate and the surrounding scenery (technically, in a‘linear optical trajectory’). This might sound complicated, but it isactually incredibly simple, and completely free of computations,representations and algorithms.

Well, yes, no, and no. The baseball player doesn’t run the numbers, but the presence of external events is somehow represented in their brain, unless you’re willing to claim that the baseball in the air outside is literally the same thing as the one represented by the idea of “baseball” and the sense-information in the player’s head. And, unfortunately, “Keep moving in a way that keeps (your representation of) the ball in a constant visual (representation) relationship with respect to (your representation of) home plate and (your representation of) the surrounding scenery” is an algorithm, that is to say, a sequence of steps to achieve a goal.

Interestingly, a lot of the ways robots do things effectively are more or less implementations of the “keep these visual targets in this sort of relationship” algorithm, more than the “build a detailed model of the physics of the world and do math on it” algorithms, at least at some level of their implementation. After all, these are the more robust ways of dealing with the world, and that’s what we want the robots to do… and yet, the algorithms are being run on standard computers like you can buy in the shop.

Two determinedpsychology professors at Leeds Beckett University in the UK – AndrewWilson and Sabrina Golonka – include the baseball example among manyothers that can be looked at simply and sensibly outside the IPframework. They have been bloggingfor years about what they call a ‘more coherent, naturalised approachto the scientific study of human behaviour… at odds with the dominantcognitive neuroscience approach’. This is far from a movement, however;the mainstream cognitive sciences continue to wallow uncritically in theIP metaphor, and some of the world’s most influential thinkers havemade grand predictions about humanity’s future that depend on thevalidity of the metaphor.

One prediction – made by the futuristKurzweil, the physicist Stephen Hawking and the neuroscientist RandalKoene, among others – is that, because human consciousness is supposedlylike computer software, it will soon be possible to download humanminds to a computer, in the circuits of which we will become immenselypowerful intellectually and, quite possibly, immortal. This concept drove the plot of the dystopian movie Transcendence (2014)starring Johnny Depp as the Kurzweil-like scientist whose mind wasdownloaded to the internet – with disastrous results for humanity.

The idea the the mind (or consciousness, if you like, both terms are equally poorly defined) is like “software” to the brain’s “hardware” is just based on the idea that you can have a brain without a mind, such as a dead person. All their organs are still there, they’re just not doing anything.However, in a state of health, the mind appears to be the thing(or at least a thing) that the brain does. The “grand prediction” goes something like this: if you assume that the brain is necessary and sufficient to “do” the mind, and, to be perfectly clear, that there are not spooks, such as the soul or other supernatural agencies, also required to “do the mind”, then if you can represent the working of the brain at a sufficiently detailed level, essentially in simulation, that simulation will also “do the mind”. No one is expecting this to be easy, and it may well be so difficult that it’s not worth doing.

Also, literally every single thing that goes wrong in the movie Transcendence is caused by neoluddite terrorists. Johnny Depp’s uploaded character is benevolent, if a little spooky. He just builds hyper-efficient solar cells, heals people’s spinal injuries, and cures diseases. Terrorists and the FBI react to this by bombing humanity back to the 1800s.

Fortunately,because the IP metaphor is not even slightly valid, we will never haveto worry about a human mind going amok in cyberspace; alas, we will alsonever achieve immortality through downloading. This is not only becauseof the absence of consciousness software in the brain; there is adeeper problem here – let’s call it the uniqueness problem – which is both inspirational and depressing.

Becauseneither ‘memory banks’ nor ‘representations’ of stimuli exist in thebrain, and because all that is required for us to function in the worldis for the brain to change in an orderly way as a result of ourexperiences, there is no reason to believe that any two of us are changed the same way by the same experience.If you and I attend the same concert, the changes that occur in mybrain when I listen to Beethoven’s 5th will almost certainly becompletely different from the changes that occur in your brain. Thosechanges, whatever they are, are built on the unique neural structurethat already exists, each structure having developed over a lifetime ofunique experiences.

This is why, as Sir Frederic Bartlett demonstrated in his book Remembering(1932), no two people will repeat a story they have heard the same wayand why, over time, their recitations of the story will diverge more andmore. No ‘copy’ of the story is ever made; rather, each individual,upon hearing the story, changes to some extent – enough so that whenasked about the story later (in some cases, days, months or even yearsafter Bartlett first read them the story) – they can re-experience hearing the story to some extent, although not very well (see the first drawing of the dollar bill, above).

At this point, this feels like a semantic quibble. The representation (the change in the brain) is both admitted to exist, but somehow not to represent, and because it’s not exact, it’s not a “copy”.

Thisis inspirational, I suppose, because it means that each of us is trulyunique, not just in our genetic makeup, but even in the way our brainschange over time. It is also depressing, because it makes the task ofthe neuroscientist daunting almost beyond imagination. For any givenexperience, orderly change could involve a thousand neurons, a millionneurons or even the entire brain, with the pattern of change differentin every brain.

So yes, it’s hard. And? Last I checked “It’s hard” wasn’t something that made humanity pack up and go home. It’s hard to climb mountains. It’s hard to build airplanes. It’s hard to put robots on Mars.

Also, at least part of the idea is that brains/minds are autopoeic. They create themselves. A potentially useful (if fraught) goal on the route to uploading would be the creation of a minimal set of self-modifying informational structures needed to create a mind. Duplicating one specific mind is certainly a more daunting prospect that creating any mind at all, but again, “It’s hard” isn’t an argument related to whether or not it’s possible.

Worse still, even if we had the ability to take asnapshot of all of the brain’s 86 billion neurons and then to simulatethe state of those neurons in a computer, that vast pattern would mean nothing outside the body of the brain that produced it.This is perhaps the most egregious way in which the IP metaphor hasdistorted our thinking about human functioning. Whereas computers dostore exact copies of data – copies that can persist unchanged for longperiods of time, even if the power has been turned off – the brainmaintains our intellect only as long as it remains alive. Thereis no on-off switch. Either the brain keeps functioning, or wedisappear. What’s more, as the neurobiologist Steven Rose pointed out inThe Future of the Brain (2005), a snapshot of the brain’s current state might also be meaningless unless we knew the entire life history of that brain’s owner – perhaps even about the social context in which he or she was raised.

I’m willing to accept that the body is a vital part of the mind, partly because the constant input of the body provides a regulation on certain aspects of the mind. However, I’m not so sure about the second part. I personally don’t have total knowledge of my life, and yet my mind appears to be as functional as it ever was. I would assume that my entire life history could be divided into two parts: those that made significant changes in my brain, and those that didn’t. The ones that didn’t make significant changes will not be present in the current state of my brain, since, by definition, they didn’t make changes in it, while those that did, will be. The distinction between a given person’s social context and life history seems like it was made more for emphasis than any sort of reasoned argument, since it’s not like the two are different from each other.

Thinkhow difficult this problem is. To understand even the basics of how thebrain maintains the human intellect, we might need to know not just thecurrent state of all 86 billion neurons and their 100 trillioninterconnections, not just the varying strengths with which they areconnected, and not just the states of more than 1,000 proteins thatexist at each connection point, but how the moment-to-moment activityof the brain contributes to the integrity of the system. Add to thisthe uniqueness of each brain, brought about in part because of theuniqueness of each person’s life history, and Kandel’s prediction startsto sound overly optimistic. (In a recent op-ed in The New York Times, the neuroscientist Kenneth Miller suggested it will take ‘centuries’ just to figure out basic neuronal connectivity.)

Meanwhile,vast sums of money are being raised for brain research, based in somecases on faulty ideas and promises that cannot be kept. The most blatantinstance of neuroscience gone awry, documented recently in a report in Scientific American,concerns the $1.3 billion Human Brain Project launched by the EuropeanUnion in 2013. Convinced by the charismatic Henry Markram that he couldcreate a simulation of the entire human brain on a supercomputer by theyear 2023, and that such a model would revolutionise the treatment ofAlzheimer’s disease and other disorders, EU officials funded his projectwith virtually no restrictions. Less than two years into it, theproject turned into a ‘brain wreck’, and Markram was asked to step down.

Again, the fact that a thing is difficult is not proof that it is impossible. Mismanagement of a project is at best, proof that the management was irresponsible or incompetent, not proof that the goals of the project are impossible. As yet, this article has not managed to link its premises (which seem to be that the computational metaphor for the brain is a metaphor, and that the brain isn’t storing representations when it storesrepresentations) with the idea that those somewhat jumbled premises somehow lead to the conclusion that uploading is impossible. Even if copying a particular mind into an executable form on a computer is impossible, elucidating the failings of the computational metaphor does not explain (or even hint at) why.

We are organisms, not computers. Get over it. Let’sget on with the business of trying to understand ourselves, but withoutbeing encumbered by unnecessary intellectual baggage. The IP metaphorhas had a half-century run, producing few, if any, insights along theway. The time has come to hit the DELETE key.

Your essay’s not good, get over yourself. The business of understanding ourselves would be better served by a coherent exploration of the problems with the computational metaphor, rather than throwing the baby out with the bathwater and claiming a total absence of knowledge in the brain. Such an exploration might not vanquish the problem of uploading, which the author seems to have poorly-examined objections to, but it would at least provide a useful cognitive exercise, and show where our understanding is supported by the metaphor and where it is undercut. In places where this essay approached the handling of the computational metaphor it did raise a number of much more interesting points, but they were unceremoniously dropped in favor of pointing out that computational neuroscience is difficult, which those of us who have actually done work in the field have already noticed.

Vape Sensor Plotting

The values calculated here are differences from the average of the first 2o samples. The X axis is time, but it’s not well-specified because I didn’t actually set a regular timer, I just collected samples as fast as possible.

As was predicted in the previous entry, the MQ-135 and MQ-3, both of which can sense alcohol, had the strongest response to vape clouds. These are the ones I’d use for the primary detection if I was building a serious vape detecting product.

The MQ-9 and MQ-8 had similar responses, but not as strong. This is kind of interesting, since they are supposed to be good for butane, propane, LPG, and hydrogen, but maybe they just do a decent job detecting light molecules with carbon in them? The MQ-2 response is interesting, since it’s sold as a LPG, propane, and hydrogen detector, but has a moderate response to vapes too.

The much lower results seems to indicate that vape clouds have no VOCs (CJMCU-1100) and no town gas or LPG (MQ-5, but I didn’t need a sensor to tell me that).

In Which Vapes May Yet Be Sensed

I’m coming to the “being a narc” thing a little late, since everyone is now having a panic about cutting agents in vapes killing people (Body count stands at ~15. The cops killed about 678 people so far this year, so y’know, keep vaping and avoid cops, it’s 45 times safer). At any rate, a school in my area was sold fantastically expensive devices that monitor areas for vaping, and report to the school administration when someone does it. The devices are on a subscription model, so they’re not just expensive once, they stay expensive.

This got me wondering what it actually takes to detect vape… vapor. Vape juice is mostly propylene glycol and glycerine, plus a dab of flavor and possibly nicotine. I have two theories about ways to detect this. One is that there will be some material produced by vaping that is detectable with a gas sensor. The other way is that phat clouds can be picked up by a particulate sensor, and the fact that it picks up smoke too is just fine, since the kids aren’t supposed to be smoking in the bathroom either.

MQ-2Combustable gasses, LPG, propane, hydrogen, probably also methane
MQ-8Just hydrogen
MQ-4Methane and natural gas
MQ-3Alcohol
MQ-6LPG, iso-butane, propane
MQ-5LPG, natural gas, “town gas”
MQ-135Carbon monoxide, carbon dioxide, ammonia, nitrogen oxide, alcohols, “aromatic compounds”, “sulfide”, and smoke
MQ-9Carbon monoxide, LPG
CMJU-1100VOCs, toluene, formaldehyde, benzene, and so on

There’s a lot of overlap in these sensors, as well as a lot of ambiguity in their datasheets. “Sulfide” isn’t a thing without whatever it’s a sulfide of. Hydrogen sulfide is a toxic and terrible-smelling gas. Cadmium sulfide is a bright yellow solid. “Town gas” is typically a mix of carbon monoxide and hydrogen. LPG is also a mix, including propane, butane, and isobutane, so having it in a list with any of those is kind of redundant.

I haven’t tested yet, but I suspect that the sensors most likely to detect sick clouds are the MQ-3, the MQ-135, and maaaaybe the CMJU-1100. The MQ-3 claims to detect alcohol, as in a breathalyzer, but the family of alcohols is actually pretty large. There’s ethyl (drinkin’ alcohol) and isopropyl (cleanin’ alcohol) and methyl (killin’ alcohol), in addition to some stuff people don’t typically think of as alcohols, like the sugar alcohols, which includes glycerine. Since glycerine is in vape juice, perhaps the sensor will detect it.

The actual mechanism of these sensors is interesting. They appear to the circuit as a resistor that changes resistance in the presence of a gas. The resistor is made of tin dioxide, which has a resistance that drops when exposed to the gasses, but it only responds quickly if the device is hot, so there is also a built-in heater for the sensors.

Because the sensors have little heaters in them, A) they smell weird when they power up for the first time and B) they take a while to stabilize. I powered them up and watched them on the Arduino serial plotter until the outputs more or less leveled out. Then I vaped at them.

Pretty much all of the sensors had some sort of response, but the thing that seemed to vary between them was that some responded faster than others. The next step is going to be logging which ones are outputting what, so I can tell which ones had the fast response and which ones had the strongest response.

The sensors also have a slight response when I just blow at them with normal breath (I have a control! I’m a scientist, doin’ a science!). Interestingly, for some of the sensors, the reaction to my normal breath was a deviation downwards/towards a lower value, while the vape reactions was uniformly a deviation upwards/towards a higher value. This suggests that including one of the sensors that indicates vaping by the sign of its change would serve as a check, since only vaping would cause both sensors to go up, and normal breath would cause one to go up and one to go down.

int readings[9] = {0,0,0,0,0,0,0,0,0};int index = 0;void setup() {Serial.begin(9600);}void loop() {//Read all the analog inputs from A0-A8 (I think they're consecutive...)index = 0;for(int ii = A0; ii <= A8; ii++ ){readings[index] = analogRead(ii);index++;}for(int jj = 0; jj < index-1; jj++){Serial.print(readings[jj]);Serial.print(",");}Serial.println(readings[index-1]);}

On Looking into Mouse Sensors

That is to say, the sensors from optical mice, rather than a sensor intended to detect the small rodent.

I have 10 boards from optical mice and three desoldered sensors. Among that bunch there are two common IC packages, a 16-pin staggered DIP (4 units) and an 8-pin staggered DIP (6 units).There is also a 20-pin staggered DIP, and two 12-pin DIP packages.

Most of the chips were made by Agilent, or Avago, a spin-off of Agilent that eventually bought Broadcom and started operating under that name. A couple are from At Lab, or as they style themselves “@lab”.

The chip interfaces are very heterogeneous. Some of them just output PS2 data and clock signals, and so are a very integrated mouse IC. Some of them output quadrature signals for x and y motion.

I had high hopes for using these mouse sensors for a couple of hacks. One of them is that they are essentially optical flow processors, so you can use them to either get velocity based on the observed motion of stationary objects from a moving platform, assuming you know how far away the objects are (and so get odometry for a moving robot by watching the ground roll by). The inverse of that is that you can also get how far away an object is assuming that it is stationary and you know your own speed (for height over ground detection in a drone, for example).

Ultimately, though, I don’t think this stash of ICs is going to do the job I want. What I want is something I can drop into projects I’m working on, and reverse engineering each of these, finding the datasheets for ICs old enough to support PS2 protocol, and so forth, would be its own hassle of a project. USB optical mice are $7 or so, so I can’t really justify the effort to get these working, sort out optics for them, etc.

On top of that, drone optical flow sensors with the optics already sorted are like $10-20, so for that use case, I can just buy the part. For robot odometry, I can use the same part, or put optics on a USB mouse that can actually plug into a recent computer, instead of decoding quadrature or PS2.

It feels kind of weird to pick up one of my old projects that I had been kind of looking forward to, and realize that it’s simply not useful or interesting, but I guess that’s just how it goes. At least I can free up that parts drawer now!

Algorithmic bar stocking

Generally, stocking a bar is a pretty simple affair. You get a big bottle of your basic alcohols (rum, gin, vodka, whiskey, tequila), smaller bottles of some other stuff (vermouth, bitters, etc), and a bunch of mixers.

Given a well-stocked bar, you can make a lot of drinks. However, you can’t make all the drinks, or rather, you shouldn’t. Not all combinations of ingredients will work well together. A rum and Coke is fine. A Coke and Coke won’t impress anyone, and a Midori and Coke would be awful, so the upper bound on the number of drinks you can make with a set of N alcohols is much lower than pure math would suggest.

I’m very gradually building a barbot, which adds a further complication: the robot only has five pumps. So from all the available alcohols, mixers, and so on, I have to choose five (there’s also a practical concern, which is that pumping soda shakes it up badly, but I’m choosing to ignore that for now).

For example, gin, tonic, vodka, orange juice, and cranberry juice would let me make a Vodka and Tonic, G&T, Screwdriver, Gin & Juice, and a Cape Cod. That’s pretty good, with 5 different drinks available from 5 different ingredients (10 if you count “shot of gin”, “glass of orange juice”, and so on as drinks).

But I want to know what the set of five liquors with the most possible mixed drinks is. To that end, I’ve downloaded the complete set of mixed drinks from the webtender, which I plan to use as the data for making my drink set.

The algorithm is another matter.

Color All The FloatCanvas Objects!

I’m drawing stuff over a background image of the ocean, which looks bluish-green. Naturally, bluish-greens and some grays don’t have enough contrast to stand out, so they kind of get lost in the image.

I initially tried calculating luminance from RGB triplets, which does work for readability, but I was using the web readability thresholds for the luminance ratio (4.5 for normal, 7 for high contrast), and it didn’t work very well because my background is sort of middling in luminance, so it punched out most of the middle range of colors, resulting in everything being either dark and similar-looking, or light and similar-looking.

I switched to RGB color distance (which, yes, isn’t perceptually flat, but this isn’t really a color-sensitive application, beyond not making them too similar). In order to figure out where my threshold should be, I wanted to get a list of all the wxPython named colors, and what they looked like, and their distance from “cadetblue”, which is about the same color as the average of my ocean background.

#!/usr/bin/python# Generate a page that previews all the colors from WXimport wxapp = wx.App(False)import wx.lib.colourdb as wxColorDBdef get_d(colorname1, colorname2="cadetblue"):target_color = wx.Colour(colorname1).Get()source_color = wx.Colour(colorname2).Get()# Euclidian distanced = math.sqrt(sum([pow(x[0] - x[1], 2) for x in zip(target_color[:3], source_color)]))return dprint("<html>")print("<body>")colors = list(set(wxColorDB.getColourList()))colors.sort(key=lambda c: get_d(c, "white"))for color in colors:cRGB = wx.Colour(color).Get()print("<div style=\"white-space: nowrap\">")print(f"<div style=\"display: inline-block; width:300px\">{color}</div>")print(f"<div style=\"display: inline-block;height:30px;overflow:auto;background-color:rgb({cRGB[0]},{cRGB[1]},{cRGB[2]}); width:100px\"> </div>")d = get_d(color, "white")print(f"<div style=\"display: inline-block\">{d}</div>")print("</div>")print("</body>")print("</html>")

That script generates an HTML page with the colors in it, ranked by distance from the given color name. I picked white for the version published here, but as you can see, the default is “cadetblue”. If you pick a color name WX doesn’t know, you’re going to have a bad time.

A distance of 80 seemed to work pretty well for me, so as a rule of thumb, 80 units of color distance gets you a distinct color in 8-bit-per-color RGB color space.

There are, of course, some problems to be aware of. For instance, distance folds hue and value together, so getting brighter or darker and remaining the same hue can make up a lot of that 80 units, without necessarily getting good contrast.

Raspbian Still Bad

The command “sudo apt-get install arduino” doesn’t get you the Arduino development environment. Instead, when you try to run it from the command line, you get “Error occured during initialization of VM. Server VM is only supported on ARMv7+ VFP”. I get that cross-compilation can be tricky, but this software didn’t get released, it escaped. Arduino isn’t exactly an obscure package.

To be fair, this isn’t because Arduino is broken. It’s because apt automatically chooses a version of Java that can’t run on the Zero W. So any package that uses Java is probably also broken, but I’m not looking into it, because I’m trying to actually do something with the Raspberry Pi. If I wanted to fuck around with a broken package chain, I’d… have gotten my fill of that like 10-13 years ago, so I guess I’d need a time machine. Really, the Pi Zero W is a lot like a time machine, taking me back to a time when Linux was a project, rather than being something you can use for projects.

If you, for some reason, want to use the Arduino IDE on a Pi Zero W, the incantation is to install Java 8 with ‘sudo apt-get install openjdk-8-jre-headless openjdk-8-jre’ and then use ‘sudo update-alternatives –config java’. Then you”ll be running a 5 year old Java and a 6 year old Arduino IDE, but at least the IDE will start up.

The Year of Linux on the Desktop is “Ha, Get Fucked”

People talk about usability, and in a lot of ways, Ubuntu is pretty close. It certainly beats Windows 10, at least for me, since you’re allowed to know what has gone wrong and fix it, instead of just rebooting whenever your computer gets infested with ghosts. I do complain about Ubuntu, but it’s usually because most things are decent, so the things that are bad are particularly egregious. And, after all, I did get what I paid for.

This time, though, I’m trying to work with a Raspberry Pi Zero W, and Raspbian. It has a little setup walkthrough that clearly took a serious blow to the head at some point, since it asks you to connect to WiFi, and then if you didn’t connect to a network, still asks if you want to download software. From what, I might ask, since there’s not a network connection?

Of course, the reason I didn’t connect to the network is that it’s hidden. Not a problem, I have the SSID on paper here… and no way to tell it to the Pi. There’s a network configurator, but it only lets you deal with unhidden networks, not enter your own SSIDs.Maybe this was done because “SSID” is one of those worrying “techie” terms, and this is supposed to be for somewhat less technical users? Protip: it’s not. It ships as a bare board in an antistatic bag, for fuck’s sake. Maybe this was not done because it’s somehow hard?

At any rate, the solution appears to be: manually edit wpasupplicant.conf.Manually edit a text file that only root can edit, in this, the Year of Our Lord 2019. I don’t have a problem with this. I have a PhD in making tiny robots go and have been using Linux for 15 years, because everything else is worse for my use cases. Normal humans, who are perhaps entering college and just want to check out Linux and maybe try writing a little Scratch or Python, they are going to have a problem with this.

Also, the same startup script asked me if my screen had black bars around the edges. It did, so I said yes (more fool me!). When I rebooted, the edges of the desktop (you know, where the UI goes) were mostly off the edge of the screen. Setting the hostname with the network config tool on the toolbar caused host name resolution errors every time I use sudo, apparently because sudo wanted “ouija1” but “ouija_1” got written into /etc/hosts. That’s not actually a valid hostname (my error), but it got written into /etc/hosts (an error by whoever wrote the alleged network config tool). Again, I know what /etc/hosts is, editing it isn’t an issue. I’m weird. For most people, this is an issue.

So in general, my experience with the Raspberry Pi and Raspbian is that it’s not ready for end users who want to use it to do things. If you want it in order to do things to it, rather than with it, and are already an experienced electronics enthusiast and Linux user, you’ll be fine.

Curious Effects Getting List Extents

I have a program that gets a list of GPS waypoints, and wants to figure out their bounding box. The naive way[1] to do this is find the maximum and minimum latitude and longitude, and use the maxes as one corner and the minimums as the other corner.

Off the top of my head, I can think of two ways to do this: Iterate the list of waypoints, comparing to the max and minimum so far, and updating as I go. The list has N points, I have to look at all of them, so O(N), so far so good.

The other way to do it is to do list comprehensions to get the latitudes and longitudes as separate lists,and then call max() and min() on each of those. I would assume that each list comprehension is O(N), and each call to max() or min() is also O(N), since they have to look through the whole list to find the maximum or minimum, and so it is 6 loops over the list (2 comprehensions, 2 max() calls, 2 min() calls), and so this is the slower way to do it.

It turns out, not so much.

I ran the code below on Repl.it and got, usually, the list comprehension version being just very slightly faster to twice as fast. Occasionally, the 10,000 instance case is slower, but not all the time.

import random from timeit import default_timer as timer#Try some different sizes of listsfor jj in [10, 100, 1000, 10000, 100000, 1000000]:#Set up N waypointswaypoints = []for ii in range(jj):lat = (random.random() * 360) - 180lon = (random.random() * 360) - 180waypoints.append({"lat":lat, "lon":lon})start = timer()# One loopmaxLat = maxLon = -float("inf")minLat = minLon = float("inf")for point in waypoints:lat = float(point["lat"])if lat < minLat:minLat = latif lat > maxLat:maxLat = latlon = float(point["lon"])if lon < minLon:minLon = lonif lon > maxLon:maxLon = lonmid = timer()# List comprehensionslons = [float(point["lon"]) for point in waypoints]lats = [float(point["lat"]) for point in waypoints]minLat1 = min(lats)minLon1 = min(lons)maxLat1 = max(lats)maxLon1 = max(lons)end = timer()#Print the resultsprint(f"{jj} points")print(f"first way {mid-start}")print(f"second way {end-mid}")print(f"speedup {(mid-start)/(end-mid)}")assert(minLat == minLat1)assert(maxLat == maxLat1)assert(minLon == minLon1)assert(maxLon == maxLon1)

So why is it faster? Clearly, I’m assuming something wrong. I suspect the main thing that I’m assuming wrong is that the constant 6 multiplied by the O(N) matters. It probably doesn’t, and that’s why we typically drop the constant multipliers in runtime comparisons. It’s likely that list comprehensions and max()/min() of iterables are calls to a very fast C implementation, and are just so much faster than my loop in Python that the fact that I’m doing 6 iterations doesn’t really matter.

Another thing that I’m assuming is that max and min are implemented as linear searches over iterables. It’s entirely possible that iterables store references to their maximum and minimum values, and just return that when asked, rather than going looking. I doubt it, since the overhead on removing an element would be large [2], but it is possible.

I haven’t looked into either of these assumptions, since timing the runs answered the question I had (“Which is faster?”), and the follow-on question (“Why?”) isn’t useful to me at this time.

[1] It does some stupid stuff around the poles and across the international date line, for example.

[2] You’ve removed the largest element. What is the new largest? Time to go searching…

Alternatively, the list could be implemented as a parallely-linked-list, where one set of links is the elements in their list order, and the other set is the elements in their sorted order, but then the list [1, 3, 5, “pickles”,<built-in method foo of Bar object at 0x1f34b881>, 6] doesn’t have well-defined links for the sorted order.

Drag and Drop Python Objects in WxPython

I’m working on a UI for a system that has agents, which have some qualities, and units, which have multiple agents. I want to be able to display each unit as a list, and drag agents from that list to other units, to reassign them.

There are a lot of examples for using drag and drop with text and files, because WxPython provides drop targets for text and files already. One way that this could be implemented is to serialize the dragged objects to JSON, drop them as text, and then de-serialize them. This has some disadvantages, notably that you end up restricted by what you can pass via JSON. I wanted to pass Python objects, so I used pickle.

What I eventually came up with is below. It uses ObjectListView, which is a great wrapper around WxPython’s ListCtrl. On drag, the selected items of the source list are pickled and passed through the Wx drag and drop mechanism. When they are dropped on another ObjectListView, they are then unpickled and added to that ObjectListView (OLV), and removed from the source OLV.

One thing that this code does leave up to the programmer is ensuring that what goes in on one side of the drag and drop is the same as what is expected out on the other side. Another, slightly more subtle thing, is that this uses pickle on the drop data, so it would be possible to have a script that generates malicious pickle data, and lets you drag it from another UI window to my script’s OLV, whereupon it unpickles into something nasty.

That said, if your attacker is sitting at your computer, launching malicious programs and dragging and dropping stuff out of them, you have already lost, and should probably invest in better door locks.

#!/usr/bin/env pythonimport wximport picklefrom ObjectListView import ObjectListView, ColumnDefn#pip install objectlistviewimport wx.lib.scrolledpanel as scrolled# UI with a few list boxes that can be drag/dropped between, and have title barsclass Agent(object):# Model of a single agent, has:# identifier (string?)# range (km)# speed (kph)# capacity (integer)def __init__(self, ident, range, speed, capacity):self.ident = identself.range = rangeself.speed = speedself.capacity = capacitydef __repr__(self):return f"<Agent: {self.ident}>"# Drag and drop Drop target that supports receiving pickled # python data structures and doing something with them. class GenericDropTarget(wx.DropTarget):def __init__(self, object):super(GenericDropTarget, self).__init__()self.object = objectself.data = wx.CustomDataObject("PickleData")self.SetDataObject(self.data)def OnData(self, x, y, defResult):#print(f"OnData({x},{y})")if self.GetData():# unpickle data and do something with itpickled_stuff = self.data.GetData()cukes = pickle.loads(pickled_stuff)# TODO We are making the assumption that a "PickleData"# actually only has a list of Agents in it. # Add some checking before making this a real thing, or# limit the type to a more-specific format like "AgentList"self.object.AddObjects(cukes)return defResultdef OnDrop(self, x, y):#print(f"OnDrop({x},{y})")return Truedef OnDragOver(self, x, y, defResult):#print(f"OnDragOver({x},{y})")return defResultdef OnEnter(self, x, y, defResult):#print(f"OnEnter({x},{y})")return defResultclass UnitPanel(wx.Panel): def __init__(self, parent, unitName="No name set"):wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)self.dataOlv = ObjectListView(self, wx.ID_ANY, style=wx.LC_REPORT|wx.SUNKEN_BORDER)self.dataOlv.SetColumns([ColumnDefn("ID", "left", -1, "ident", minimumWidth=100),ColumnDefn("Range", "right", -1, "range", minimumWidth=60),ColumnDefn("Speed", "right", -1, "speed", minimumWidth=60),ColumnDefn("Capacity", "right", -1, "capacity", minimumWidth=60)]) self.agents = []self.dataOlv.SetObjects(self.agents)self.dataOlv.Bind(wx.EVT_LIST_BEGIN_DRAG, self.OnDragInit)# Set up a drop target on the listviewdt = GenericDropTarget(self.dataOlv) self.dataOlv.SetDropTarget(dt) # Set up a title for this boxself.unitLabel = wx.StaticText(self, id=wx.ID_ANY, label=unitName)mainSizer = wx.BoxSizer(wx.VERTICAL)mainSizer.Add(self.unitLabel, proportion=0, flag=wx.ALL, border=5)mainSizer.Add(self.dataOlv, proportion=1, flag=wx.ALL|wx.EXPAND, border=5)self.SetSizer(mainSizer)def populate(self, units):self.agents = []# for unit in units:# self.agents.append(Agent(unit["ident"], unit["range"], unit["speed"], unit["capacity"]))# self.dataOlv.SetObjects(self.agents)for unit in units:a = Agent(unit["ident"], unit["range"], unit["speed"], unit["capacity"])self.dataOlv.AddObject(a)#self.draggableURLText.Bind(wx.EVT_MOTION, self.OnStartDrag)def OnDragInit(self, event): # Get all the selected items from this listselected = self.dataOlv.GetSelectedObjects()# Pickle them and put them in a custom data objectpickled_selection = pickle.dumps(selected)drag_obj = wx.CustomDataObject("PickleData")drag_obj.SetData(pickled_selection) #Create a drag and drop source from this ObjectListViewsrc = wx.DropSource(self.dataOlv) src.SetData(drag_obj)print("Drag started")result = src.DoDragDrop(wx.Drag_DefaultMove) if result == wx.DragCopy:# We don't copy because agents are hardwareself.dataOlv.RemoveObjects(selected)elif result == wx.DragMove:# Remove the data from here, add it to another listself.dataOlv.RemoveObjects(selected)else:# Default, do nothingprint("Nothing, nothing, nothing at all")class AssetFrame(wx.Frame):def __init__(self):wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, title="ObjectListView Demo", size=(800, 600))self.panel = scrolled.ScrolledPanel(self, id=wx.ID_ANY)self.mainSizer = wx.BoxSizer(wx.VERTICAL)self.panel.SetSizer(self.mainSizer)self.panel.SetupScrolling()self.Show()def populate(self, config):for unit in config["units"]:unit_panel = UnitPanel(self.panel, unitName=unit["name"])unit_panel.populate(unit["agents"])self.mainSizer.Add(unit_panel) if __name__ == "__main__":app = wx.App(False)# We're going to need to be able to populate the frame from the config,# so represent the data as a data structure and initialze with thatconfig = {"units": [{"name": "Unimatrix 01","agents": [{"ident": "7 of 9", "range": 10, "speed": 10, "capacity": 12},{"ident": "Third of 5", "range": 10, "speed": 10, "capacity": 12}]},{"name": "Unit 2","agents": [{"ident": "u2s1", "range": 10, "speed": 10, "capacity": 12},{"ident": "u2a2", "range": 10, "speed": 10, "capacity": 12},{"ident": "u2a3", "range": 10, "speed": 10, "capacity": 12}]},{"name": "Unit Foo","agents": [{"ident": "bar", "range": 10, "speed": 10, "capacity": 12},{"ident": "baz", "range": 10, "speed": 10, "capacity": 12},{"ident": "quux", "range": 10, "speed": 10, "capacity": 12}]},{"name": "Enterprise","agents": [{"ident": "Galileo", "range": 10, "speed": 10, "capacity": 12},{"ident": "Copernicus", "range": 10, "speed": 10, "capacity": 12}]},{"name": "GSV Insufficent Gravitas","agents": [{"ident": "GCU Nervous Energy", "range": 1000000, "speed": 3452334, "capacity": 13452342},{"ident": "GCU Grey Area", "range": 1000000, "speed": 234523546, "capacity": 234562312}]}] }frame = AssetFrame()frame.populate(config)app.MainLoop()

I called the unpickled data “cukes” because this is demo code, and I was being silly. A cucumber is, after all, what you get when you undo the process of making pickles. You may want to change that if you copy/paste this into production code.