Pull to refresh

Comments 35

Я не нашел, а где класс Angles используется. Т.е. мне показалось, что его специально совершенствовали, но для чего. Углы принадлежат Атомам, Атомы скорее всего Молекулам… Молекулы РНК, а что такое Цепочка тогда? Можно увидеть как-то все куски кода?
Но я же пишу

Итак есть объект РНК (RNA). Он является наследником более общего объекта Chain (Цепь из молекул) (например, могут быть еще ДНК, белки и т.д.). Каждое РНК состоит из множества молекул (нуклеотидов) (Molecule). В данном случае молекула может быть четырех видов (наследники Molecule) — Cytosine, Uracil, Guanine, Adenine. Каждая молекула в зависимости от типа состоит из 28-33 атомов (Atom). У каждого атома есть три расчетных угла


Там примерно так

public class RNA : Chain
{
    public Molecule[] Molecules;
}
public class Molecule
{
    public Atom[] AllAtom;
}
public class Atom
{
    public Angles Angles;
}
 


ну и конкретные углы рассчитываются, через ряд методов — это я опускаю

ну вы надеюсь понимаете я упрощаю.

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

Например, конструктор класса Chain содержит параметр MolCount поидее общее количество молекул, но сами молекулы только в RNA появляются если верить комментарию.

Вы не обижайтесь плюсик я вам поставил, но помимо плюсика должна быть ещё и ясность.
Я всего лишь не хочу чтобы вы утонули в деталях. Если честно, молекулы вообще уже есть на уровне базового класса т.е. в Chain, в РНК он уже просто конкретизированы, т.е. аденины, урацилы создаются там. Дефект упрощения — уж извиняйте. Что касается MolCount, то в RNA подается первичная последовательность, а число молекул выделяется из неё и передается в Chain

public RNARealise(RNASeq argSeq)
            : base(argSeq.Len)
{
    PrimaryRNASeq = argSeq;
}
 


Но это вроде как мелочи, не сильно относящиеся к собственно идеи. Но вы спрашиваете, я отвечу — даже если минусик поставите :)
если кодом то так

public class Chain
{
    /// Молекулы в цепи
    public Molecule[] Molecules;
}
 
/// Цепь РНК
public class RNARealise : Chain
{
    public RNASeq PrimaryRNASeq;
 
    public RNARealise(RNARealise argRNA)
    {
        PrimaryRNASeq = argRNA.PrimaryRNASeq;
        Molecules = new Molecule[argRNA.PrimaryRNASeq.Len + 1];
    }
}
 
Да и наверно не обойдусь еще еще такой конструктор

public RNARealise(RNASeq argSeq)
           : base(argSeq.Len)
{
    PrimaryRNASeq = argSeq;
    Create3D();
}
А разве не должно быть проверки на затирание argGeneration==generation-1 && argTimeID <=CurrentMaxTimeID?
Чем плохо наклонировать объектов, а потом написать функцию Set, которая будет копировать данные? Разве что будет использоваться больше памяти, но зато не будет проверок на границы массива при обращении.
Кстати, что произойдет с вашим методом в многопоточной программе?
Отвечу вначале по поводу многопоточности. Вот какая штука — программа то многопоточная, и этот код запускается в отдельном потоке. Хотел было написать, что можно запустить и второй поток с созданием новых независимых объектов. Но тут вспомнил, что появился паттерн Singleton — так сказать дефект объектной модели. Ну тогда надо поколдовать, чтобы класс Chain знал, что за поток работает — выдавал бы через Time в соответствующем потоке. Но все это лирика. Потоки не обеспечивают загрузки процессоров. Это хорошо видно у меня 2 четырехядерных процессора, и при загрузки одной программы работает только 12% процессорного времени. Можно загрузить еще одну программу — и работает тогда 24% и т.д. Поэтому если и делать параллельные вычисления, то нужно не многопоточность — а многопроцессность. Тогда одна программа выполняет главный цикл, а еще скажем 6 программ (процессов) рассчитывают асинхронно. Но им (процессам) нужно тогда постоянно воссоздавать последние «хорошие» состояние РНК (BestRNA). Т.е. 6 раз создавать граф цепи и только потом рассчитывать. (кстати, тоже самое и в потоковом представлении — только еще с невозможность эффективно распределить потоки по процессорам). Поэтому выигрыш не очень большой. Поэтому превращать это в параллельные вычисления пока не спешу… хотя когда будет отработан сам подход к биовычислениям — можно подумать о распределенном проекте. Но сейчас рано.
Извиняюсь, написал глупость.
Что касается затирания. Если ничего не напутал. У меня есть комментарий: "(такое может быть только между текущим и прошлым поколением)". Т.е. как раз когда поколения меняются, то и происходит затирание. Т.е. если «клонирование» происходит от объекта из прошлого поколения (как правило это последние время в текущем поколении, т.е. в примере с индексом 4), то новый объект затирает данные по времени 0, но тем самым сменяется поколение.
Я к тому, что нужно проверить, не затерт ли объект новым поколением. Вы ведь предыдущее поколение разрешаете.
«Чем плохо наклонировать объектов, а потом написать функцию Set, которая будет копировать данные? Разве что будет использоваться больше памяти, но зато не будет проверок на границы массива при обращении.»

Если правильно понял вопрос — клонировать объекты намного дороже по времени, в этом то весь и примус.
Наклонировать нужно только один раз, а затем много раз вызывать Set переиспользуя объекты RNA.
Как это один раз. Вам нужно иметь другой объект углов, вы будите их клонировать ВСЕ ВРЕМЯ. Делаете RNA locRNA = argRNA.Clone(); и там клонируете 1000 раз объект класса Angles, а иначе вы затрете предыдущие состояние.
Или вы думаете создать две совершенно разных объекта RNA, в одном хранить «лучшие» значение, а во втором «расчетное», а Set вызывать копируя из «лучшего значения» в «расчетное». Так? Если нет лучше напишите псевдокодом.
Да, так.
RNA a = b.AllocateCopy();
a.SetFrom(b);
// change a
// calculate a
a.SetFrom(b);
// etc
Если схема сложнее, то можно их хранить точно так же в закольцованном массиве.
По поводу рассмотренного примера. Я пока бегло читал все думал: «А почему нельзя описать взаимное расположение молекул в виде динамических связей (к примеру диф. ур. типа „вход-выход“) и не запустить симуляцию дискретной модели?»
Описываем каждое требование по углу и взаимному расположению уравнением вида "(a0*s^2 + a1*s + a2)*Out(s) = b0*In(s)", строим дискретную модель в пространстве состояний и пускаем симуляцию. Моделируем до тех пор, когда система будет близка к равновесию…
Задав нормальные демпферы (коэфф. a1) можно ожидать плавный выход к равновесному состоянию => не очень большое время симуляции. Памяти будет меньше задействовано (ничего копировать не надо, не строить графы).
Возможно оффтоп, но что-то всплыло в голове.
И кстати «Приспособленец», субя по всему, хорошо впишется в данную модель. Нужно создать лишь один экземпляр динамической модели и скармливать ей при каждом вызове симуляции следующего шага вектор состояния (два числа для указанных выше уравнений), коэффициенты матричных уравнений после дискретизации и значение управления (In(s)).
Извините… ошибся малость. С паттерном только знакомлюсь.
Получается что и коэффициенты передавать не нужно будет. Просто для моделей с разными наборами коэффициентов возвращать разные экземпляры, т.е. набор коэффициентов будет ключем в реализации паттерна.
Боюсь, что об этом надо говорить с понимание сути биовычислений. Это если вы готовы обсуждать — мне надо написать отдельную статью. Надо?

А так похоже проблема в том, что уравнение вы тут никакое не напишите. Прямо не известно какие должны быть углы. Задаются определенные взаимоотношения — условия при которых образуются определенные водородные связи между молекулами. Если нужные ВСЕ водородные связи образовались — то отлично. Но для многоспиральных молекул — такого состояния я еще не разу не находил :)… алгоритм легко попадает в локальный минимум и выйти не может. Вообщем там все не просто… хотите будем обсуждать…
Впрочем тут моя первая статья на эту тему Целенаправленный поиск в задаче сворачивания третичной структуры РНК. Она довольно устарела, но как базис для понимания подходит. Тут зарезервировано место для второй статьи (может скоро опубликуют, тогда смогу выложить текст). Тоже пока идет подготовка к публикации, уже успела устареть.

Но в статье на хабре — мог бы написать так сказать более популярную статью.
Тема жутко интересная. Я в ней пока нуб (за исключением практики применения генетического программирования — что видимо совсем не то ), но очень хочется «просвелеть». Так что люто заплюсую за «по-простому о сложном».
Насчет уравнений… Если условия нелинейны, типа «if (x<0) then f1(x) else f2(x)» и т.п., то наверное действительно трудно будет применить то, что я подразумевал. Хотя есть смежные реализации динамических систем с нелинейностью. Вплоть до рекуррентных нейросетей. Просто я люблю самоорганизацию, и если корректно описать, то, возможно, удастся запустить симуляцию в поисках равновесного состояния.
Если найду время освоить суть задачи, возможно удастся изложить свой вариант решения (т.к. я понимаю, предпочитаю и умею). Даже если вариант будет нежизнеспособен, возможно это наведет кого-нибудь на еще одно решение.
ГА и рекуррентные нейросети отдыхают… проверено. Я пришел к выводу, что ИИ-методы тут малопригодны, хотя сам по специализации как раз ИИ-шник. Наиболее перспективно тут — теория игр, эта задача по сворачиванию очень похожа на игры в шахматы. Напишу скоро поясняющую статью.
Вообщем понял, что одной статьей уж никак не обойдусь. Поэтому если меня поддержат обратной связью будет серия статей.

прошу принимайте первую статью из серии Часть №1. Введение в биовычисления по сворачиванию. От белков к РНК
Мне очень не нравится получившаяся архитектура — вы много говорите о чистоте ООП и самым грубом образом нарушаете инкапсуляцию статическими полями. Класс Chain вообще солянка из приватных полей объекта и статических оберток, честно не понял какой в этом смысл. Такой код очень сложно отлаживать и поддерживать.

Поведение объектов не очевидно и зависит банально от создания ещё одного инстанса класса Chain. Кстати, самый простой тест на хорошую архитектуру — перенесите один любой класс в другой проект, как есть. Если программа не собирается — значит явно есть косяк )

По-моему, у вас тут горе от ума — суть ООП не в том, чтобы смоделировать объекты реального мира один в один как есть. Нужно создать гибкую, ясную и производительную программную модель.

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

Вот как бы вы это исправили? Как какому то объекту знать какое сейчас текущие время? Предложите.

А с этим: "суть ООП не в том, чтобы смоделировать объекты реального мира один в один как есть" не соглашусь. Не возможно создать гибкую, ясную и производительную программную модель, если абстракция реального мира не соответствует вашей модели. Еще смотрите DDD.

Ну, и затем примененный усовершенствованный паттерн легко превратить в библиотеку, которой передается класс, указываются «свойства во времени», и объект начинает жить во времени. Наружу видно только быстрое клонирование в указанных случаях. Внутри библиотек делается создается динамический код, через возможности отображения в .Net — и все готово.

Поведение объектов тут просто инкапсулировано, не видна лишь реализация клонирования, а она и не должна быть видна. Причем заметим, что в другом случае вы изменили бы модель и пришлось бы изменять не реализацию, а интерфейс. Т.е. ни какой прозрачности при изменении. И углы были бы не в атомах — это нормально?
Но в имеющихся условиях это тем не менее меньшие зло.

Наоборот, это то, что полностью ломает всю концепцию ООП. Решается это очень просто, например, класс Angles возвращает массивы, вместо одного значения, а уже вызывающий код сам выбирает какое из значений ему нужно. Вариантов много, но так как вы сделали лучше не делать… особенно если хотите это оформлять в виде библиотеки.
И ради чего вы предлагаете возвращать не нужные массивы вызывающему коду? Да еще, чтобы он не знамо как выбирал то, что ему нужно — он тоже не знает какое время. Вы и его будите учить тому что не надо — передавая ему текущие время?

Вот в этом и разница. Для меня важна чистота ООП не ради абстрактной чистоты, а как удобство и правильность модели в смысле ее соответствия реальности.

Если сделать то как вы хотите — оформить в виде библиотеки уже нельзя — пользовательские классы начинают знать о времени, «выбирать». Это их перегружает, и нельзя отделить собственно получившийся паттерн от предметного кода.
Если хотите оставить текущий API, можно пробрасывать Chain через конструктор Angles, и уже на его Time завязываться.
Не серьезно. Какие — то углы начинают агрегировать ВСЮ цепь. Ради чего? Вы предлагает создать двухсторонние ссылки — это еще БОЛЬШАЯ цена.

Думаете я не обдумывал все возможные варианты? Они все хуже. И это кажется правильный пример, когда в ООП использовать статические члены. Суть времени как раз в том, что оно глобально. И нельзя полностью отказаться от глобальных переменных, их надо конечно уменьшить и не применять там где надо. но здесь это надо.

А вообще какие у вас претензии к статическим членам, что тут не соответствует ООП?
Нарушение инкапсуляции, разве не очевидно? Ваше глобальное время получается слишком глобальным вот в чем проблема. В один момент времени можно работать только с одним экземпляром класса, все это чревато трудно-уловимыми багами в дальнейшем. Особенно если вы планируете выложить это в общий доступ (за что, кстати, респект).

Это ваше дело как строить свою программу, но выкладывать такое в хаб «Совершенный код» это уже слишком. Прошу прощения за резкость, но я много времени потратил на ковыряние в унаследованном говно-коде и такие «проблемки» сразу бьют по глазам.
Ваша резкость была бы уместна, если бы предложили лучший выход. А так пока увы — мимо.
И в «Совершенным коде» это потому, что это лучшие решение из возможных. Можете не соглашаться, но вы не берете во внимание несколько аспектов. А статические члены — это меньшие зло.

Давайте подумаем спокойно. Нарушение инкапсуляции кого? Чем это проблема?
Ну вот посмотрите сами: вы предлагаете иметь 1000 ссылок от атома к цепи, и/или 1000 раз передавать атомам локальное время в качестве параметров. И это чем то лучше, чем использовать глобальную переменную уровня цепи (chain)?
Sign up to leave a comment.

Articles