✍ diale.org

Webpage of Tiago Charters de Azevedo

Início/Start Arquivo/Archive AdNauseum Notas/Notes RSS


Filtro Kalman 1D

... implementação simples de um filtro de Kalman usando Arduino (ou outra coisa qualquer)

2018/04/07-23:47:57

Em 1960, num artigo1 que agora já é famoso, Rudolf Kalman construiu um filtro que consiste em minimizar a variância (de variáveis aleatórias gaussianas) associada a uma previsão através de um algoritmo definido por recorrência: obter uma nova estimativa usando a anterior adicionando um termo de correcção proporcional ao erro de previsão. Simples, não?

A ideia deste texto é explicar de uma forma simples a implementação de um filtro de Kalman num Arduino e construir um sensor de intensidade luminosa usando um LDR. O hardware necessário é o seguinte:

Hardware e código inicial

É fácil de encontrar um código exemplo para se ligar um LDR ao Arduino. Fica aqui uma versão simples ;)

int sensorPin = A0; 
int sensorValue = 0;

void setup(){ 
  Serial.begin(9600); 
} 

void loop(){ 
  sensorValue = analogRead(sensorPin); 
  Serial.println(sensorValue); 
} 

O gráfico seguinte mostra a variação da luminosidade quando tapo e destapo o LDR com a mão. Vê-se claramente as oscilações de 50Hz da rede eléctrica na luz do candeeiro.

Filtro de Kalman 1D

Quero então estimar o valor da luminosidade da sala onde me encontro. Para isso admito que a intensidade luminosa é constante (ou antes que necessita de ser "quase" constante de modo a que seja possível fazer uma medição) e que o valor medido y possa ser decomposto na soma de um valor médio m mais um termo de flutuação gaussiano v com variância r (valor inicial). Assim

y:=m+v

Admito também que para cada valor da luminosidade se tem a estimativa x dada por

x:=m+w

com o mesmo valor médio e flutuações gaussianas mas com variância q (valor inicial). Note-se que w e v são variáveis aleatórias gaussianas com média zero e independentes.

O filtro de Kalman admite que as sucessivas aproximações (modelo) são obtidas linearmente das anteriores, i.e. xf:=a xi . Como estou a admitir que os sucessivos valores da luminosidade são constantes ponho a:=1

x:=x

e

p:=p+q

onde p é variância da aproximação seguinte (são todas variáveis gaussianas independentes, a variância da soma é a soma das variâncias).

Ficam assim estabelecidas as regras de evolução da primeira parte do algoritmo de Kalman. Vamos à segunda parte. Esta segunda parte corresponde a estimar/prever a aproximação seguinte que é escrita em termos da aproximação anterior e o erro de previsão, i.e.,

x:=x+k(y-x)

onde k é um parâmetro a determinar, usualmente chamado de ganho do filtro, e y-x o erro de previsão. Como determinar então o valor de k? O valor de k é determinado de forma a minimizar a variância da nova estimativa x+k(y-x).

Calculando a variância desta última quantidade obtém-se

p:=(1-k)^2*p+k^2*r

É condição necessária para que se tenha um extremo relativo da variância que a derivada de p em ordem a k seja zero. Isto dá:

k:=p/(p+r)

e

p:=p*r/(p+r)

Curiosamente, ou talvez não, esta última fórmula corresponde formalmente ao valor do paralelo de duas resistências com valores p e r.

Fico assim com as duas últimas fórmulas que precisava:

k:=p/(p+r)
x:=x+k(y-x)
p:=(1-k)*p

O gráfico seguinte mostra o que acontece quando tapo e destapo o LDR (linha azul) numa escala de 0-1023. As linhas a verde e vermelho correspondem à implementação de filtros de Kalman com parâmetros diferentes.

Happy hacking!


/* Simply implementation of a 1D Kalman filter */
/* for Arduino using a LDR. */

/* Some other examples can be done with this file, */
/* e.g. sonar, temperature measurements, sky is the limit. */
/* Happy hacking! */
  
/* Author: Tiago Charters de Azevedo  */
/* Maintainer: Tiago Charters de Azevedo  */
/* URL: http://diale.org/ */
/* Version: 0 */

/* Copyright (c) - 2018 Tiago Charters de Azevedo */

/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3, or (at your option) */
/* any later version. */

/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the */
/* GNU General Public License for more details. */

/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 51 Franklin Street, Fifth Floor, */
/* Boston, MA 02110-1301, USA. */

/* Commentary: */

int sensorPin = A0; 
int sensorValue = 0;

// 1st filter parameters
float q=0.125;
float r=32;
float p=1023;
float x=0;
float k=0;

// 2nd filter parameters
float q1=4;
float r1=100;
float p1=1023;
float x1=0;
float k1=0;

void setup(){ 
  Serial.begin(9600); 
} 

void loop(){ 
  sensorValue = analogRead(sensorPin); // read sensor value

  // 1st Kalman filter
  p=p+q; 
  k=p/(p+r);
  x=x+k*(float(sensorValue)-x);
  p=(1-k)*p;

  // 2nd Kalman filter
  p1=p1+q1; 
  k1=p1/(p1+r1);
  x1=x1+k1*(float(sensorValue)-x1);
  p1=(1-k1)*p1;

  
  //Print values
  Serial.print(sensorValue); // raw value
  Serial.print(", ");
  Serial.print(int(x)); // 1st filter output
  Serial.print(", ");
  Serial.print(int(x1)); // 2nd filter output
  Serial.println("");
} 

1.R. Kalmam, A New Approach to Linear Filtering and Prediction Problems, Transactions of the ASME–Journal of Basic Engineering, 82 (Series D): 35-45. 1960

Etiquetas/Tags: kalman, arduino, filtro

A verdade, nada mais do que a verdade

Notas sobre o Teorema de Godel (exposição informal)

2018/03/18-00:17:02

Vamos construir uma máquina de calcular que escreve expressões compostas pelos seguintes símbolos neg P N ( ).

Por expressão entenda-se uma lista não vazia composta por estes cinco símbolos. Uma expressão X é "printável"1 se a máquina a conseguir escrever ("printar"). Admitimos que a máquina está programada de a modo a escrever expressões que pode imprimir, i.e., gasta todo o seu tempo a imprimir expressões.

Chama-se norma de uma expressão X à expressão composta X(X); por exemplo, a norma de P neg é P neg (P neg). Uma frase válida tem uma das seguintes formas:

  1. P(X)
  2. P N(X)
  3. neg P(X)
  4. neg P N(X)

Se associarmos, informalmente, a três dos símbolos anteriores um significado podemos ler uma qualquer frase válida. Assim associamos os seguintes significados a P, N e neg:

Com esta interpretação podemos dizer que P(X) é uma frase verdadeira se, e só se, X é printável1; do mesmo modo PN(X) é verdadeira se, e só se, a norma de X poder ser escrita, neg P (X) é verdadeira sse2 X não poder ser escrita e neg P N(X) é verdadeira se a norma de X não poder ser escrita. Assim as definições anteriores permitem-nos falar em português, e com rigor, sobre o que afirmam cada uma das frases escritas pela máquina e o que significa uma expressão verdadeira. Estas são de facto, auto-afirmações, efectuadas pela máquina, são frases que nos dizem algo sobre a máquina que as escreve. A máquina durante o seu funcionamento descreve o seu próprio funcionamento, semelhante a um organismo consciente.

Assim concluímos que a máquina está bem definida, i.e., funciona bem, e que todas as frases que por ela são escritas são expressões verdadeiras. Por exemplo, se a máquina escrever P(X), isto significa que X pode ser realmente escrito (X será escrito mais tarde ou mais cedo); da mesma forma se num instante posterior a máquina escrever P N(X) então X(X) também aparecerá mais tarde. Admitamos agora que X pode ser escrito pela máquina, será que podemos concluir que P(X) também o será? Se X pode ser escrito pela máquina então a frase P(X) é verdadeira, mas não sabemos, de facto, se P(X) pode ser escrito pela máquina, ou seja, se P(P(X)) é verdadeira.

Será possível a máquina escrever todas as afirmações verdadeira que falam sobre ela?

A resposta a esta pergunta é, um surpreendentemente, não! Para podermos verificar isso temos que encontrar uma frase que seja verdadeira, i.e., que afirme algo verdadeiro sobre a máquina, e que a máquina não consiga escrever. Basta construir uma frase, uma expressão, que afirme a sua não "printabilidade".

Uma candidata seria: Esta frase "esta frase não pode ser escrita" não pode ser escrita. Ou seja neg P N (neg P N), que afirma que a norma de neg P N não pode ser escrita. Por definição de expressão verdadeira, a frase anterior é verdadeira se a norma de neg P N não pode ser escrita, mas a norma de neg P N é exactamente a frase neg P N (neg P N)!

Algumas frases apressadas

Ref: Smullyan, R M (2001) "Gödel's Incompleteness Theorems" in Goble, Lou, ed., The Blackwell Guide to Philosophical Logic. Blackwell

1. Vou usar "printável" para dizer o mesmo que "pode ser escrita".

2. sse = se, e só se

Etiquetas/Tags: Godel, teorema, notas, Smullyan

Word list

Funções em elisp para manipulação de ficheiros de palavras.

2018/03/18-00:17:02

Na antiga versão do jogo do monopólio existia uma carta da sorte que começava com a expressão "Levou um tiro de um amigo..." e normalmente o que se seguia consistia no pagamento de uma conta do hospital.

Um amigo não me deu um tiro mas fez-me uma pergunta, e no meu caso a procura da resposta leva a quase uma visita ao hospital. A pergunta era: " Será que existem palavras de 5 letras em português que verifiquem o padrão seguinte?"

1 5 9 1 7 
2 6 0 5 6 
3 7 3 4 0 
4 8 2 8 9 
Nota: cada número representa uma letra diferente.

Não interessa muito de onde aparece a motivação da pergunta, interessa-me mais a procura da resposta. Há largos meses que tinha começado a ler o volume 4 do TAOCP Combinatorial Algorithms, Part 1 onde, entre outras coisas, é usada a Stanford GraphBase, uma lista de 5757 palavras em inglês com cinco letras, para exposição dos vários algoritmos que aí são descritos.

Propus-me então replicar1 alguns dos resultados descritos no TAOCP usando palavras em PT. Para isso precisava de um dicionário e uma maneira de começar a extrair a informação. O resultado é este pequeno conjunto de funções em elisp. Muito ainda está por fazer, por exemplo, o aspell usa um sistema de compressão para prefixos e sufixos, cuja sintaxe só descobri hoje, e que aumenta o número de palavras disponíveis para se brincar.

;;; wlist.el --- Emacs tools for manipulating word-files 
;; word-files, meaning a file with words in it, one word per line.

;; Author: Tiago Charters de Azevedo <tca@diale.org>
;; Maintainer: Tiago Charters de Azevedo <tca@diale.org>
;; Created: Fev, 17, 2012
;; Version: .1
;; Keywords: words
;; URL: http://diale.org/wlist.html

;; Copyright (c) 2012 Tiago Charters de Azevedo

;; This file is not part of GNU Emacs.

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.

;;; Commentary:
;; None.

;; Code:

(defvar wlist-max-lenght 
  0
  "")

(defvar wlist-regexp-pt
  "[aerisontcdmlupvgbfzáhçqjíxãóéêâúõACMPSBTELGRIFVDkHJONôywUKXZWQÁYÍÉàÓèÂÚ].+"
  "Regular expression for a portuguese word; see aspell.")

(defun wlist-looking-at-size ()
  "Returns the length of a word on the beginning of a line (pt-PT)."
  (interactive)
  (if  (looking-at wlist-regexp-pt)
      (length (match-string-no-properties 0))
    0))

(defun  wlist-looking-at-size-plus-1 ()
  (interactive)
  (forward-line 1)
  (wlist-looking-at-size))

(defun wlist (size)
  "Removes all sized SIZE words from `current-buffer'; asks SIZE."
  (interactive "n") 
  (with-current-buffer (current-buffer)
    (goto-char (point-min))
    (save-excursion  
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (when (not (= size (wlist-looking-at-size)))
          (delete-region (point) (line-end-position)))
        (forward-line 1))))
  (wlist-delete-blank-lines))

(defun wlist-delete-blank-lines ()
  (interactive)
  (with-current-buffer (current-buffer)
    (goto-char (point-min))
    (save-excursion  
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (delete-blank-lines)
        (forward-line 1)))))

(defun wlist-insert-header ()
  "Inserts a not so beautiful header."
  (goto-char (point-min))
  (insert (format "File name: %s\n" (file-name-nondirectory (buffer-file-name)))
          (format "Number of %s sized words: %s\n" size (line-number-at-pos (point-max)))))

(defun wlist-hamming-dist-list (lst1 lst2)
   "For equal length lists is the number of positions at which the 
corresponding lists are different."
  (if  (and lst1 lst2
            (= (length lst1) (length lst2)))
      (if (equal (car lst1) (car lst2))
          (wlist-hamming-dist-list (cdr lst1) (cdr lst2))
        (+ 1 (wlist-hamming-dist-list (cdr lst1) (cdr lst2))))
    0))

(defun wlist-hamming-dist (str1 str2)
  "For equal length strings is the number of positions at which the 
corresponding strings are different."
  (wlist-hamming-dist-list (string-to-list str1) 
                              (string-to-list str2)))

(defun wlist-remove-bslash ()
  "Remove /* properties form word-file. No plurals or m/f, etc,... 
Needs to be changed correctly for portuguese."
  (interactive)
  (with-current-buffer (current-buffer)
    (goto-char (point-min))
    (save-excursion  
      (while (search-forward-regexp "\\(.+\\)\\(/.+\\)" nil t)
        (let ((word-s (match-string-no-properties 1)))
          (replace-match word-s))))))

(defun wlist-max-size ()
  "Gets the maximum size of all words in a word-file."
  (interactive)
  (with-current-buffer (current-buffer) 
    (goto-char (point-min))
    (save-excursion  
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (setq wlist-max-lenght (max (wlist-looking-at-size) (wlist-looking-at-size-plus-1) wlist-max-lenght))))))

(defun wlist-file-size (size)
  "Determines and creates a file of all the words with size SIZE."
  (interactive "n")
  (let ((dic-words (buffer-string)))
    (with-temp-buffer
      (insert dic-words)
      (wlist size)
      (append-to-file (point-min) (point-max) 
                      (concat default-directory (format "%s.wl" size))))))

(defun wlist-all-files-sizes ()
  "Determines all the words from size 2 to `wlist-max-size' 
and save them to separate files *.wl; it takes a few minutes to finish."
  (interactive)
  (if (= wlist-max-lenght 0)
      (wlist-max-size))
  (let ((size 2))
    (while (<= size wlist-max-lenght )
      (wlist-file-size size)
      (incf size))))
  
(defun wlist-same-pos (n)
  (interactive "x")
  (with-current-buffer (current-buffer) 
    (goto-char (point-min))
    (save-excursion  
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (looking-at wlist-regexp-pt)
        (if (not (equal (nth (- (car n) 1 )
                        (string-to-list (match-string-no-properties 0)))
                   (nth (- (cadr n) 1)
                        (string-to-list (match-string-no-properties 0)))))
;;          (message (match-string-no-properties 0)))
            (delete-region (point) (line-end-position)))
        (forward-line 1)))
    (wlist-delete-blank-lines)))

(defun wlist-file-same-pos (n)
  (interactive "x")
  (let ((i (car n))
        (j (cadr n))
        (words (buffer-string)))
    (with-temp-buffer
      (insert words)
      (wlist-same-pos (list i j))
      (append-to-file (point-min) (point-max) 
                      (concat default-directory (format "%s_%s.wl" i j))))))


(defun wlist-find-all-hamming-dist-word (word dist)
  (with-current-buffer (current-buffer) 
    (goto-char (point-min))
    (save-excursion  
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (looking-at wlist-regexp-pt)
        (if (not (= dist (wlist-hamming-dist word (match-string-no-properties 0))))
            (delete-region (point) (line-end-position)))
        (forward-line 1)))
    (wlist-delete-blank-lines)))

(defvar wlist-buffer-content-list nil
  "")

(defun wlist-buffer-length ()
  (count-lines (point-min) (point-max)))
  
(defun wlist-buffer-alist ()
  (interactive)
  (with-current-buffer (current-buffer) 
    (goto-char (point-min))
    (let ((wl-buffer-list nil))
      (save-excursion  
        (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
          (looking-at wlist-regexp-pt)
          ;;    (push 'new-item accumulator)
        (push (match-string-no-properties 0) wl-buffer-list)
        (forward-line 1)))
      (reverse wl-buffer-list))))

(defvar wlist-word-link nil
  "")

(defun wlist-hamming-dist-word-insert (word dist)
  "Looks for the hamming DIST of word WORD, inserts all the words found after WORD."
  (setq wlist-word-link nil)
  (with-current-buffer (current-buffer) 
    (goto-char (point-min))
    (save-excursion
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (looking-at wlist-regexp-pt)
        ;; Looks for word in file and save point, for inserting.
        (if (equal word (match-string-no-properties 0))
            (setq w-point (list (point) (line-end-position))))
        (forward-line 1)))
    (save-excursion  
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (looking-at wlist-regexp-pt)
        (if (= dist (wlist-hamming-dist word (match-string-no-properties 0)))
            (push (match-string-no-properties 0) wlist-word-link))
        (forward-line 1)))
    (goto-char (cadr w-point))
    (insert (format " %s" (mapconcat 'concat word-link " ")))))

(defun wlist-hamming-dist-insert-buffer (dist)
  "Builds the world link with DIST and inserts the result after every word in buffer."
  (let ((wlist-list (wlist-buffer-alist)  ))
    (dolist (word wlist-list)
      (wlist-hamming-dist-word-insert word dist))))

(defun wlist-insert-after-word (word in-word)
  "Insert IN-WORD in `curren-buffer' after WORD."
  (with-current-buffer (current-buffer) 
    (goto-char (point-min))
    (save-excursion
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (looking-at wlist-regexp-pt)
        (if (equal word (match-string-no-properties 0))
            (replace-match (format "%s %s" word in-word)))
        (forward-line 1)))))

(defun wlist-hamming-dist-word-list (word dist)
  "Looks for the words with hamming DIST of word WORD; returns all of the in a list."
  (setq wlist-word-link nil)
  (with-current-buffer (current-buffer) 
    (goto-char (point-min))
    (save-excursion  
      (while (< (line-number-at-pos) (line-number-at-pos (point-max)))
        (looking-at wlist-regexp-pt)
        (if (= dist (wlist-hamming-dist word (match-string-no-properties 0)))
            (push (match-string-no-properties 0) wlist-word-link))
        (forward-line 1))))
  (reverse wlist-word-link))

(defun wlist-word-link-next (word dist)
  "Returns the next link of word-link with hamming DIST of word WORD."
  (car (wlist-hamming-dist-word-list word dist)))

(defun wlist-one-word-link (word dist n)
  "Returns a word-link from WORD whit hamming distance DIST."
  (let ((word-link word)
        (new-word (wlist-word-link-next word dist)))
    (while (and new-word (<= 0 n))
      (push new-word word-link)
      (wlist-one-word-link new-word dist (- n 1)))))
            
(provide 'wlist)


1. Existe tamanho palavrão em português?.

Etiquetas/Tags: aspell, emacs, elisp

Teaser for my new guitar amplifier

1/4W to 3W class a mosfet amplifier

2018/03/18-00:17:02

Here is my new class A mosfet amplifier 1/4W to 3W guitar amp.

More pics and sound samples later.

Etiquetas/Tags: DIY, guitar, amplifier

WAMP - 1 W guitar amplifier

A simple two stage mosfet class a guitar amplifier

2018/03/18-00:17:02

Sounds much better than any chip amp, overdrives nicely with a booster in front of it. Sounds clean with good compression, high output impedance, can drive 8/16Ohms cabs (even 4Ohm).

Some oscilloscope pics:

Have fun!

Etiquetas/Tags: class a, mosfet, guitar, amplifier, diy

Wharfedale 15 woofer

... que tenho aqui em casa

2018/03/18-00:17:02

Finalmente consegui descobrir qual o altifalante que tinha aqui para casa (era do meu avô): um Wharfedale de 15 polegadas. Precisa de um restauro mas o cone e a spider parecem estar em boas condições!

Etiquetas/Tags: Wharfedale, 15'', woofer, W15/cs

Nova descobertta - chemoton

Blog de vitorino ramos

2018/03/18-00:17:02

O muito saudoso VRamos da a-formiga-de-langton.blogspot.com está agora aqui: http://chemoton.wordpress.com

P.S.

Só agora, passados estes anos, é que reparei que ao meu antigo blog (abundantetempolivre) foi atribuído dois dos prémios Formiga:

Bons tempos esses de 2003!

Etiquetas/Tags: blog, VRamos

Voto srtq

Durante o meu passeio habitual pelo arxiv...

2018/03/18-00:17:02

Durante o meu passeio habitual pelo arXiv.org dei na secção de matemática com o seguinte trabalho: Square root voting in the Council of the European Union: Rounding effects and the Jagiellonian Compromise. Recordo-me de se ter falado disto a propósito do método de voto proposto pelo governo polaco. Uma procura mais sistemática revela ainda o trabalho: Voting in the European Union: The square root system of Penrose and a critical point.

Claro que estes trabalhos requerem uma leitura mais aprofundada. Uma pesquisa no Google dá mais alguma coisa, apanha-se até o artigo do expresso onde se lê:

... proposta da "raiz quadrada", também conhecida por regra de Penrose e que assenta na ideia de que o peso de cada país deve ser proporcional à raiz quadrada da respectiva população...
Para se perceber em que consiste o sistema de voto pela raiz quadrada é necessário ver-se umas coisas antes. Note-se que o artigo de Penrose intitula-se "The elementary statistics of majority voting", a referência completa pode ser vista no primeiro trabalho que cito no início. Elementar, não?

O primeiro passo é analisar a qualidade/poder de cada voto dentro de cada país. Penrose define este poder como a probabilidade de um voto individual mudar o resultado da votação assumindo que todos os outros votos são aleatórios (ora aqui está um bom ponto para se pegar para argumentar contra o voto "raiz quadrada"). O resultado que é usado nas notícias que saíram a este respeito é aquele que se obtém depois de se admitir que a votação é ou "sim" ou "não" que o número de votantes, N, é muito maior do que 1, e depois usar a aproximação de Stirling; que nos dá a probabilidade de um voto mudar o resultado final da votação final, P=1/sqrt(N). Esta é a "lei raiz quadrada de Penrose".

Compare-se com o que foi dito na altura!

Etiquetas/Tags: sqrt, voto, raiz quadrada, matemática, democracia

Voltímetro para electricistas amadores

do Tratado de iniciação à T.S.F.

2018/03/18-00:17:02

Etiquetas/Tags: electricidade, DIY

Voltei

Voltei, tenho voltado, após dez anos de intervalo,

2018/03/18-00:17:02

Voltei, tenho voltado, após dez anos de intervalo, às minhas confusões (confissões) habituais, nada de novo, tudo na mesma: Wittgenstein, Schoenberg e Burroughs. Insano estacionamento.

"What can be shown cannot be said." (Wittgenstein)

"All writing is in fact cut-ups. A collage of words read heard overheard. What else? Use of scissors renders the process explicit and subject to extension and variation." (Burroughs)

Etiquetas/Tags: Wittgenstein, Schoenberg, Burroughs

Palavras chave/keywords: página pessoal, blog

Criado/Created: NaN

Última actualização/Last updated: 07-04-2018 [23:47]


GNU/Emacs

1999-2018 (c) Tiago Charters de Azevedo

São permitidas cópias textuais parciais/integrais em qualquer meio com/sem alterações desde que se mantenha este aviso.

Verbatim copying and redistribution of this entire page are permitted provided this notice is preserved.