Category: лытдыбр

Category was added automatically. Read all entries about "лытдыбр".

with Cat The Cat

К предыдущему.

У меня верхняя граница перехода между весами 12 повторений, сброс между подходами 10% (примерно - 46 и 42 кг или 42 и 38 кг, такие уж у нас гантели) и всего два подхода (я использую вариант круговой тренировки, там ещё приседания или становая). Статья про метод сбрасывает 10%, граница перехода между весами 8 и используется три подхода.

Поскольку я использую круговую тренировку, мне надо ограничивать количество подходов в одной тренировке, иначе будет истощение нервной системы (перетренированность), см. HST или я просто не буду выполнять нужное (вес или повторения в подходе). Поэтому у меня один-два подхода на приседания или становую и два подхода на жим - в последнем меньше мышц задействуется. И вес и количество повторений я стараюсь увеличивать между тренировками (опять же, см. принципы HST), то есть, через два-три дня, а не еженедельно.
with Cat The Cat

Разное.

Выясняем с коллегой причины проблем сборки некоей БД с несколько изменённым хранилищем. Оба смотрим на, вроде бы, один и тот же RPM - md5sum одинаковый, имена файлов тоже. В моей копии RPM некоторый файл отсутствует, у коллеги он присутствует. Качали из одного места, прошу прощения за каламбур.

Восхищённый ситуацией, я решил поделиться с ним Палкой с Резиновой Нахлобучкой, в котором подходящую к ситуации последнюю строчку имеет стих:

Туман поутру.
Вдалеке забивают сваю:
Бам-бам-бам-бам!
....
Бусон

Коллега в ответ говорит, что у него сейчас 11 утра (утро, то бишь), за окном туман и где-то, судя по звукам, забивают сваю.
with Cat The Cat

Закон больших чисел.

Подписавшись на твиттер госпожи или господина, чириканье которой (которого) понравилось через сердечки того, на кого уже подписан, получаешь совсем другой результат, чем ждал.

Вместо редких мощных вещей - как ожидалось через долетающие сердечки, - получаешь поток чего-то странного. А потом до тебя доходит, что за тебя выбирали интересное из этого потока. Ведь даже стоящие часы дважды в день показывают верное время, а тут дни бегут, как у тебя минуты.
with Cat The Cat

Если спутники летают с юга на север...

...то я видел спутник.

Если нет, то видел НЛО - оно не мигало, как самолёт. Может, это был метеор под большим углом к поверхности Земли, конечно, однако яркость сперва плавно нарастала, а потом плавно снижалась, медленнее, чем у падающей звезды, которых я тоже насмотрелся недели две-три назад.

Окрестности подмосковного Чехова невероятно интересны.
with Cat The Cat

Колесо и четыре ноги.

Колесо в живой природе существует только в микромире - жгутики у бактерий и красные кровяные тельца.

А в макромире нет. И его пришлось изобретать, сравнивая с четырьмя ногами животных.

Но это всё философия.

Короче говоря, подражать природе можно, но путь человеческой мысли, это, скорее, путь колеса или винта или турбины самолёта.
with Cat The Cat

Разное

Игра «Свидетель» гениальна в своей задумке и очень слабая в мобильной версии. В некоторых местах надо смотреть на предметы под разными углами и на айпаде это просто невозможно. В мобильной версии нет даже действия «присесть»!

Однако за ощущение «Ага! Вот, как!» после решения очередной головоломки смело можно давать приз. ;)

Получил некий интересный результат в моих экспериментах с оптимизацией через Лагранжиан. Думаю, скоро поделюсь. Пока проблема в том, что мой комп для программирований-хобби сломался, я использую чужой, а у него и памятью, и ср всем другим тоже плохо. И неохота создавать новый ключ для гит-Абакан.
with Cat The Cat

Комбинаторные разборщики - преобразователи монад.

Начало и продолжение.

Как обычно, этот пост - литературный модуль. Его можно скопировать в .lhs файл и поэкспериментировать. Однако, нового кода здесь будет мало.

Нам понадобятся:
>-- мы автоматически выведем стандартные типы для нашего нового разборщика.
>{-# LANGUAGE GeneralizedNewtypeDeriving #-}
>-- MonadState - get/set не создаются обычным методом.
>{-# LANGUAGE StandaloneDeriving #-}
>-- использование String (type String = [Char]) в качестве аргумента реализации класса.
>{-# LANGUAGE TypeSynonymInstances -#}
>-- MonadState имеет два параметра.
>{-# LANGUAGE MultiParamTypeClasses #-}
>-- ghc требует. ;)
>{-# LANGUAGE FlexibleInstances #-}
>
>import Control.Applicative -- Applicative и Alternative для списков.
>import Control.Monad
>import Control.Monad.List -- ListT.
>import Control.Monad.State -- State и StateT.

Напомню тип разборщиков из первой главы:
 [(a,String)]

Обычно, монада состояния (state monad) имеет тип type State s a = s -> (a,s). То есть, преобразование состояния есть функция от состояния в результат и (возможно, изменённое) состояние.

Если мы обобщим наш разборщик на произвольные структуры данных, то получится вот такой тип:
>type GenInputParser i a = i -> [(a,i)]
>type Parser1 a = GenInputParser String a

Итак, наш обобщённый разборщик имеет структуру, напоминающую структуру преобразований состояния, мешается только список пар. Что приятно, мы получили возможность выполнять разбор по данным, отличным от списка, например, по деревьям или множествам. Или, даже, графам.

Мы можем сделать наш разборщик ещё более обобщённым, сделав выбор (список) более общим:
>type GenParser ch i a = i -> ch (a,i)
>type Parser a = GenParser [] String a

Посмотрите на определение списка:
*Main> :i []
data [] a = [] | a : [a] 	-- Defined in ‘GHC.Types’

Конструктор типа списка [] имеет один аргумент. После подстановки в параметр ch он раскроется в [(a,i)]. Параметр i преобразуется в String и, в результате, мы получим наш тип из самого начала: type Parser a = String -> [(a, String)].

Позволю себе обратить внимание, что здесь мы обобщили методы разбора и пересоздали старый тип из более общего.

Теперь посмотрим на определение преобразователя монад StateT:
newtype StateT s (m :: * -> *) a
  = StateT {runStateT :: s -> m (a, s)}
Отлично видно, как похожи GenParser и StateT. newtype здесь используется для указания компилятору, что StateT новый тип, для него будут использованы свои реализации классов типов.

Попробуем собрать разборщик из предыдущей главы, но используя преобразователи. Это очень просто:
>-- NX добавлено, чтобы 1) отличать от других типов и 2) для молодёжности.
>newtype ParserNX a = ParserNX { runParserNX :: StateT String [] a}
>    -- GeneralizedNewtypeDeriving
>    deriving (Functor, Monad, Applicative, Alternative)
>-- standalone deriving:
>deriving instance MonadState String ParserNX

Вот такая магия. При создании сего текста я просто следовал указаниям компилятора в виде ошибок типов.

На данный момент мы уже имеем кучу определённых примитивов - many, some, <$>, <*>, <|> и тому подобное. Всё определено так, как мы делали в предыдущих главах.

Определим недостающие примитивы и метод разбора:
>item :: ParserNX Char
>item = do
>    (c:cs) <- get
>    put cs
>    return c

>char :: Char -> ParserNX Char
>char c = check (==c) item

>check :: (a -> Bool) -> ParserNX a -> ParserNX a
>check pred p = do
>    a <- p
>    if pred a then return a else empty

>parse :: String -> ParserNX a -> Either String a
>parse text (ParserNX p) = case runStateT p text of
>    [] -> Left "no parse"
>    ((a,""):_) -> Right a
>    ((_,rest):_) -> Left $ "error somewhere near "++take 20 rest++"..."

Вот результат запусков:
*Main Control.Applicative> parse "aabbabba" (many (char 'a' <|> char 'b'))
Loading package transformers-0.4.1.0 ... linking ... done.
Loading package mtl-2.2.1 ... linking ... done.
Right "aabbabba"
*Main Control.Applicative> parse "aabbabbac" (many (char 'a' <|> char 'b'))
Left "error somewhere near c..."

Позволю себе подвести итог.

Итак, синтаксический разбор - преобразование состояния (текста, в данном конкретном случае) с вычислением промежуточного результата, обрамлённое в тип, поддерживающий недетерминированный выбор (список в нашем конкретном случае).

Мы выяснили это, обобщив конкретный тип.

По структуре типа (и необходимым операциям, определяющим его) можно выяснить вложение комбинаторов монад, что приводит к уменьшению кода программы.
with Cat The Cat

Ещё к вопросу про Clojure.

Мне повезло настолько, что я пользовался Clojure задолго до его (её?) появления, лет за семь до. Тогда Clojure назывался Tcl и платформой, на которую он опирался, был... весь юникс. Примерно так.

Как Clojure является клеевым языком, так и Tcl таковым являлся. Как Clojure представляет из себя "улучшенный" Лисп, так и Тикль представляет собой Лисп без лишних круглых скобочек и с добавленными другими скобочками.

Так что я имею представление, что такое клеевые языки.

Это чрезвычайно мощная штука.

Но вот пришлось мне для документооборота писать разбор SQL, чтобы сгенерировать кое-какой код по нему. И выяснилось, что в Тикле это чрезвычайно тяжело.

Собственно, сейчас мне было бы легче, поскольку сейчас я программист посильнее. Поэтому если я возьмусь за Clojure, мне будет легче, чем на тикле тогда.

Мне это просто неинтересно.
with Cat The Cat

Как ускорить попарную нормализованную корреляцию в тысячу раз.

Нормализованная корреляция - это вычисление скалярного произведения двух последовательностей, деленного на произведение их длин.

C(si,sj) = sumk=1..L[siksjk/(|si| |sj|)]

Если длина последовательности 1000, а последовательностей тоже 1000, то всего получается 1000*1000*(1000-1)/2=499500000 умножений и чуть меньше сложений. То есть, сложность O(LN2). Здесь L - длина последовательности, а N - их количество

Если мы можем выделить некую существенную часть из каждой последовательностей, и некое вычисление над этими частями дает приближение к корреляции, то мы можем отфильтровать заведомо плохие пары. Если сия существенная часть вычисляется быстро или может быть вычислена зараннее.

В принципе, последовательности можно условно разделить на две категории - хорошие и плохие. Для хороший последовательностей очень просто вычислить существенную часть, для плохих - тяжело. Плюс, плохие последовательности, скорее всего, слабо коррелируют с самими собой, сдвинутыми по времени.

Хорошие последовательности имеют спектр вида 1/f - "розовый" шум или даже красный шум, с большими низкими частотами и амплитуда частоты (примерно) уменьшается с её возрастанием. Низкие частоты вносят большой вклад в корреляцию, поэтому разумно брать их в качестве существенной части.

Плохие последовательности имеют спектр вида 1 - "белый" шум, где все частоты представлены равномерно. Это производная "красного" шума. Здесь существенную часть выбрать сложно, ведь корреляция по одной частотной составляющей может быть перекрыта любыми другими частотами.

Если говорить о практической пользе, то "хорошие" последовательности наблюдаются в колебаниях цен на продукты, а "плохие" - в "выгоде", (ценаi+1-ценаi)/ценаi.

Ну, как уже было сказано, если взять пяток-другой (десяток-другой) коэффициентов разложения Фурье последовательностей с меньшими частотами, то можно примерно предсказать коэффициент нормализованной корреляции для двух последовательностей.

С плохими последовательностями такой трюк не пройдет.

Для плохих последовательностей не работает даже разложение по сингулярным значениям (это квадраты собственных значений).

Но для них придумали особый подход - проекции на случайные вектора.

Мы генерируем псевдослучайные последовательности, числом M и длиной L, со значениями 1 и -1, и выполняем с ними свертку всех последовательностей. Получается вектор длиной M, sketch vector, набросок.

Так вот, доказано, что расстояние между нормализованными векторами-набросками пропорционально корреляции между последовательностями: D(x, x) = 2(1+corr(x,y)). D - расстояние, x - временная последовательность, x - нормализованный вектор-набросок. Отсекая по расстоянию, мы отсекаем по корреляции. Можно отсечь все с корреляцией менее порога (колебания цены на схожие продукты), можно отсечь все с корреляцией выше порога (конкурирующие компании).

Все. Остались только технические вопросы - как сделать подходящий генератор псевдослучайных чисел, как считать побыстрее в процессе добавления элементов в последовательности и тп. Это, натурально, решается очень просто.