Часовой пояс: UTC + 3 часа




Начать новую тему Новая тема / Ответить на тему Ответить  Сообщений: 6 
  Пред. тема | След. тема 
В случае проблем с отображением форума, отключите блокировщик рекламы
Автор Сообщение
 

Member
Статус: Не в сети
Регистрация: 20.03.2011
Откуда: Москва
В общем сабж в картинке: задали написать оптимизацию методами дихотомии, золотого сечения и фибоначчи. Все работает, но с золотым сечением проблема: число итераций слишком велико: в 1.5-2 раза больше, чем дихотомией, а должен отличаться не более, чем на 10%. Ошибок никаких не нашел, вот алгоритм:
спойлер
#77

Собственно код: есть абстрактный класс Solver с шаблонным методом Solve, собственно есть сабклассы дихотомии, золотого сечения и фибоначчи, т.к. вся разница между ними в методе определения очередных точек. Для наглядности проект целиком приложу:
solver.cs
Код:
using System;
using System.Collections.Generic;

namespace Spo
{
    public struct ResultData
    {
        public readonly double A, B, Left, Right, Functionleft, Functionright;

        public ResultData(double a, double b, double left, double right, double functionleft, double functionright)
        {
            A = a;
            B = b;
            Left = left;
            Right = right;
            Functionleft = functionleft;
            Functionright = functionright;
        }

        public override string ToString()
        {
            return string.Format("{0:f}\t{1:f}\t{2:f}\t{3:f}\t{4:f}\t{5:f}", A, B, Left, Right, Functionleft,
                                 Functionright);
        }
    }

    public abstract class Solver
    {

        protected readonly Func<double, double> Function;
        protected readonly double L;
        protected double A, B, Lambda, Mu;

        public double Result { get; private set; }

        protected Solver(Func<double, double> function, double a, double b, double l)
        {
            Function = function;
            A = a;
            B = b;
            L = l;
        }

        public IEnumerable<ResultData> Solve()
        {
            if (IncorrectData)
                throw new ArgumentException();
            PlaceStartPoints();
            do
            {
                double y1 = Function(Lambda);
                double y2 = Function(Mu);
                yield return new ResultData(A, B, Lambda, Mu, y1, y2);
                if (y1 > y2)
                {
                    A = Lambda;
                    PlaceNewPointsIfGreater();
                }
                else
                {
                    B = Mu;
                    PlaceNewPointsIfLower();
                }
            } while (Condition);
            Result = Middle;
        }

        private double Delta
        {
            get { return B - A; }
        }

        protected double Middle
        {
            get { return (A + B)/2; }
        }

        protected virtual bool IncorrectData
        {
            get { return L < 0; }
        }

        protected virtual bool Condition
        {
            get { return Delta > L; }
        }

        protected abstract void PlaceStartPoints();
        protected abstract void PlaceNewPointsIfGreater();
        protected abstract void PlaceNewPointsIfLower();
    }
}

Код:
using System;

namespace Spo
{
    public class GoldenRatio : Solver
    {
        private readonly double k;

        public GoldenRatio(Func<double, double> function, double a, double b, double l)
            : base(function, a, b, l)
        {
            k = (Math.Sqrt(5) - 1)/2;
        }


        protected override void PlaceStartPoints()
        {
            NewLambda();
            NewMu();
        }

        protected override void PlaceNewPointsIfGreater()
        {
            Lambda = Mu;
            NewMu();
        }

        protected override void PlaceNewPointsIfLower()
        {
            Mu = Lambda;
            NewLambda();
        }

        private void NewLambda()
        {
            Lambda = A + (1 - k) * (B - A);
        }

        private void NewMu()
        {
            Mu = A + k*(B - A);
        }
    }
}


Вот ссылка на проект целиком (vs 11)
https://dl.dropbox.com/u/90956817/Spo.rar

_________________
I would tell you a joke about UDP, but you probably wouldn't get it.



Партнер
 

Member
Статус: Не в сети
Регистрация: 18.12.2003
Честно говоря, в проекте разбираться лень...Но, что сразу настораживает, что простейшая вычислительная задача решается с дикими извращениями, это как в Москву через Владивосток ездить или из пушек по воробьям стрелять. Похоже на горе от ума. Проще надо быть, проще :-) Абстрактные классы, наследование, вычисляемые извратно свойства, коллекции,перечислители, шаблоны. О господи...зачем ?! :facepalm: Еще бы лямбда-выражения, регулярку и функционалы приспособили. :D Простейшей консольной программы хватило бы (на любом языке выглядели бы просто). И не надо было специально искать грабли. Не удивляюсь, что сегодняшние программы для обработки одного килобайта требуют гигабайты памяти и кучу процессорного времени :D Совет: не надо демонстрировать крутизну, KISS принцип должен рулить и будет меньше проблем. Профессионализм в том и состоит, чтобы использовать наиболее подходящие и простые способы решения задачи, а не то, что самое крутое и модное. :-) На месте преподавателя сразу бы отправил переделывать...

Если еще актуально, могу посмотреть на выходных. Интересно...как звучала постановка задачи...

_________________
Сам себе режиссёр


 

Member
Статус: Не в сети
Регистрация: 20.03.2011
Откуда: Москва
sop18 да уже сделал. На самом деле ничего страшного как раз нет: из 300 строк функционального кода получилось 200 строк ООП. Проблемы решаются в одном месте, объекты имеют свои поля и не зарятся на чужие. Что касается до отработки методов на не самой сложной задаче - это все окупилось, когда найденая ошибка исправила проблемы сразу во всех местах, чего копи-пастом не добиться. KISS как раз состоит в том, что есть один класс, в котором есть вся логика, с шаблонным методом Solve, а наследники просто переопределяют абстрактные методы расстановки точек (там было еще дублирование, сейчас я его окончательно убрал). Лучше иметь 5 классов по 50 строк, чем 1 на 250. Это только кажется, что код сложный, в функциональном стиле он выглядел бы еще хуже, инфа 100%

Алсо, шаблонов тут нет, да и в шарпе их в принципе нет :) А из генериков у меня используются только стандарный IEnumerable<T>. Но если интересно - вот тут всегда будет лежать последняя версия, если интересно: качайте и смотрите. Все замечания рассмотрю: учеба на то и учеба, чтобы не натыкаться на грабли. Мне показалось, что такое разделение будет наиболее простым. Если найдете способ сократить код без дублирования и нарушении логики (типа метода рассчета значений последовательности Фибоначчи, который доступен из кода метода Дихотомии) - то с радостью приму помощь. Вот собственно ссылка на проект (т.к. она при обновлении файла не меняется, то она будет ссылаться всегда на последнюю версию):
https://dl.dropbox.com/u/90956817/Singl ... zation.rar

_________________
I would tell you a joke about UDP, but you probably wouldn't get it.


 

Member
Статус: Не в сети
Регистрация: 18.12.2003
Psilon
Для учебы, согласен, вполне можно, чтобы освоить новое. Можно тренироваться. :-)
Надеюсь, гляну на выходных что там, самому интересно. Да и часто чужой взгляд бывает полезен, а то глаза на свой код намыливаются. По себе знаю. :-)

...Шаблоны...я и имел в виду этот шаблонный класс ( IEnumerable<T> ) :-)
А как сама задача звучала ?

Кстати, когда "из 300 строк функционального кода получилось 200 строк ООП." не всегда полезно. Платой за удобства ООП служит скорость. И часто весьма суровая. Работаю программистом, оптимизацией занимался и для С++ и С#.
Вот только что на работе видел....программа открывает несколько файлы xml на несколько кбайт и читает их ... почти минуту, а то и более :D Вот где кошмар, а если файлы с данными большие будут :D
Да и был не так давно у самого Microsoft'a как то сервис-пак на Visual Studio, весом ~ 300 Мб, так ставится от часа до 4х, в зависимости от быстродействия компьютера. :diablo:
Так что ООП не панацея и слишком увлекаться не стоит. Просто один из инструментов, далеко не универсальный.
Видел товарищей, разбирался с их кодом, настолько навороченным, что падала сама Visual Studio. От внутренней ошибки. :D Отлаживать этот код и переносить на другие платформы - тот еще ад

_________________
Сам себе режиссёр


 

Member
Статус: Не в сети
Регистрация: 20.03.2011
Откуда: Москва
sop18 да, у меня была ситуация, когда выпадала внутренная ошибка фреймворка. Но в 4.5 пофиксили (отправлял тикет в МС). Скорость - не принципиально, лучше программировать понятный код, чем быстрый. Как говорил один хороший товарищ:
Цитата:
Также вызывает беспокойство, связанное с такого вида рефакторингом, возможное падение
производительности. Прежний код выполнял цикл while один раз, новый код выполняет его три раза. Долго выполняющийся цикл while может снизить производительность. Многие программисты отказались бы от подобного рефакторинга лишь по данной причине. Но обратите внимание на слово «может». До проведения профилирования невозможно сказать, сколько времени требует цикл для вычислений и происходит ли обращение к циклу достаточно часто, чтобы повлиять на итоговую производительность системы. Не беспокойтесь об этих вещах во время проведения рефакторинга. Когда вы приступите к оптимизации, тогда и нужно будет об этом беспокоиться, но к тому времени ваше положение окажется значительно более выгодным для ее проведения и у вас будет больше возможностей для эффективной оптимизации.

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


Ага, мне человек уже посоветовал понятный код:
Цитата:
я говорю что незачем совать в классы и т.п.

но вообще вот золотое сечение например:
Код:
(define (golden f e x y)
  (define len (- b a))
  (cond
    [(< len e) (/ (+ a b) 2)]
    [else (define x1 (- b (/ len phi.0)))
          (define x2 (+ a (/ len phi.0)))
          (if (< (f x1) (f x2))
              (golden f e x1 b)
              (golden f e x2 b))]))


_________________
I would tell you a joke about UDP, but you probably wouldn't get it.


 

Member
Статус: Не в сети
Регистрация: 20.03.2011
Откуда: Москва
Хотя мой код для дихотомии оказался не сильно проще:
Код:
let rec dichotomy f a b e l =
    let middle = (a+b)/2.
    let lambda = middle - e
    let mu = middle + e
    if b - a < l then
        middle
    else
    let FLambda = f lambda
    let Fmu = f mu
    if FLambda < Fmu then
        dichotomy f a mu e l
    else
        dichotomy f lambda b e l
let f x = x**2.0
let result = dichotomy f -1. 2. 0.00001 0.0001
printfn "%f" result

_________________
I would tell you a joke about UDP, but you probably wouldn't get it.


Показать сообщения за:  Поле сортировки  
Начать новую тему Новая тема / Ответить на тему Ответить  Сообщений: 6 
-

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Перейти:  

Лаборатория














Новости

Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB | Kolobok smiles © Aiwan