powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Тестирование и QA [игнор отключен] [закрыт для гостей] / Тестирование функций вещественной переменной. +
11 сообщений из 11, страница 1 из 1
Тестирование функций вещественной переменной. +
    #40143766
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Результат разговоров с жемини

Весь наш разбор, сравнения инструментов (Z3, cvc5, AngouriMath, Daisy) и логика краш-теста на последовательности Мюллера полностью в вашем распоряжении.

Для C# лучшими бесплатными вариантами будут:

1. Использовать AngouriMath (раз уж мы о нем говорили)
В отличие от Math.NET, AngouriMath умеет считать вещественные функции с точностью, значительно превышающей double (например, со спецификацией в 50 или 100 значащих цифр вместо 15-17 у double).
Специализированные библиотеки длинной арифметики для .NET
Mpir.NET или BigRational — обертки над легендарной сверхбыстрой сишной библиотекой GMP/MPFR. Это мировой стандарт для вычисления математических функций с точностью до миллионов знаков после запятой.

PeterO.Numbers (ExtendedFloat / ExtendedBigDecimal) — полностью написанная на C# отличная бесплатная библиотека (доступна в NuGet). Она поддерживает вычисление натурального логарифма (EDecimal.Log) с абсолютно любой заданной вами точностью.

Краткая сводка инструментов
1. AngouriMath (Символьный движок / CAS)Что это: Библиотека компьютерной алгебры (Computer Algebra System), написанная полностью на чистом C#.Как работает: Она оперирует математическими выражениями как аналитическими деревьями (анализирует строки, берет производные, интегралы, раскрывает скобки, упрощает дроби).Арифметика: Использует рациональную арифметику произвольной точности (большие целые числа BigInteger для числителя и знаменателя).Для чего идеален в вашем плане: * Пройти последовательность Мюллера без потери точности (так как нет округления, дроби считаются абсолютно точно).Автоматически генерировать аналитические коэффициенты рядов Маклорена для длины меридиана любой глубины, не считая их вручную на бумаге.

2. Z3 (SMT-солвер от Microsoft)Что это: Автоматический доказыватель теорем (Satisfiability Modulo Theories solver).Как работает: Он не умеет упрощать формулы или брать производные. Вместо этого вы задаете ему логическое утверждение (теорему) и ограничения. Z3 пытается доказать истинность этой теоремы для всех возможных входных значений или найти хотя бы один контрпример (значение плавающей точки, на котором код выдаст ошибку).Арифметика: Строго моделирует побитную логику стандартов плавающей точки (IEEE-754), включая субнормальные числа, -0.0, NaN и Infinity.Для чего идеален: Для автоматического доказательства условий монотонности (ваши smoke_test_3 и smoke_test_4 ) без необходимости запускать циклы на 100 миллионов итераций.

Стоит ли начать делать и с Z3 тоже?Да, стоит, но строго в качестве следующего (продвинутого) шага.Включать Z3 в самый первый прогон со студентами может быть тяжело из-за разницы в концепциях. Вот идеальная методическая цепочка для ваших занятий:Этап 1: Отрезвление (Мюллер на double vs AngouriMath). Студенты видят, как падает обычный код, и как символьный движок легко решает проблему за счет точных дробей.

Этап 2: Автоматизация (Длина меридиана в AngouriMath). Вместо того чтобы брать готовые коэффициенты $C_0..C_8$ из статьи, студенты пишут формулу общего члена ряда эллиптического интеграла, а AngouriMath сама генерирует точные коэффициенты для кода. Этап 3: Формальная верификация (Z3). Вот здесь вы говорите: «А теперь давайте докажем монотонность функции len около нуля. Мы можем крутить цикл 25 минут, а можем попросить Z3 проверить все $2^{64}$ вариантов double за полсекунды математически». С чего начать интеграцию Z3?Для вашей задачи с меридианами Z3 лучше всего применить для проверки условий монотонности.Поскольку в Z3 встроена теория вещественных чисел, студентам нужно будет переписать тригонометрический полином на языке солвера и запустить проверку. Если солвер вернет UNSAT (формула невыполнима) на утверждение «существует точка, где функция убывает», значит, монотонность строго доказана.Резюме: Начните завтра с демонстрации Мюллера на AngouriMath — это даст быстрый, наглядный и понятный результат. А параллельно (например, со следующей недели или в качестве задания повышенной сложности) дайте студентам задачу подключить Microsoft.Z3 для автоматического доказательства аксиом монотонности из вашей статьи. Такой комплексный подход закроет все аспекты: от длинной арифметики до формальных методов Microsoft.
...
Рейтинг: 0 / 0
Тестирование функций вещественной переменной. +
    #40143769
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AngouriMath -- вычеркиваем из списка работ и полезных сайтов.

Почему это висит у AngouriMath? Проект, судя по всему, заброшен автором или обновляется крайне редко. Они просто забыли (или не успели) вырезать старую ссылку из кода своей документации, и теперь их сайт «фонит» вредоносной ссылкой. Заходить туда сейчас точно не стоит.
...
Рейтинг: 0 / 0
Тестирование функций вещественной переменной. +
    #40143779
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Эмм.
Пока результаты оригинальной неустойчивой последовательности Мюллера для флоатов и даблов.
Код: C++
1.
2.
3.
4.
5.
6.
7.
#pragma once
template<typename D>
D E(const D &xn, const D  &xn1) {
  D xn2;
  xn2 = D(108.0) - ( D(815.0) - D(1500.0) / xn ) / xn1;
  return xn2;
}
Последовательность подбиралась так, что любая конечная мантисса влечет предел 100, а должен быть 6.
# class is 'real' 0 4.000000000000000000 1 4.250000000000000000 2 4.470588235294115975 3 4.644736842105217534 4 4.770538243625082941 5 4.855700712568562949 6 4.910847498660629640 7 4.945537395530507752 8 4.966962408040998866 9 4.980042204293013697 10 4.987909232795786352 11 4.991362641314552206 12 4.967455095552267608 13 4.429690498308829660 14 -7.817236578459315410 15 168.939167671064581100 16 102.039963152059272034 17 100.099947516249699220 18 100.004992040972439327 19 100.000249579237305397 20 100.000012478620163847 21 100.000000623921607712 22 100.000000031195796169 23 100.000000001559783414 24 100.000000000077989171 25 100.000000000003893774 26 100.000000000000198952 27 100.000000000000014211
# class is 'single' 0 4.000000000000000000 1 4.250000000000000000 2 4.470588684082031250 3 4.644744873046875000 4 4.770706176757812500 5 4.859214782714843750 6 4.983123779296875000 7 6.395431518554687500 8 27.632629394531250000 9 86.993759155273437500 10 99.255508422851562500 11 99.962585449218750000 12 99.998130798339843750 13 99.999908447265625000 14 100.000000000000000000 15 100.000000000000000000 16 100.000000000000000000 17 100.000000000000000000 18 100.000000000000000000 19 100.000000000000000000 20 100.000000000000000000 21 100.000000000000000000 22 100.000000000000000000 23 100.000000000000000000 24 100.000000000000000000 25 100.000000000000000000 26 100.000000000000000000 27 100.000000000000000000
Написано при помощи шаблона CRTP
numbers_aa.zip
...
Рейтинг: 0 / 0
Тестирование функций вещественной переменной. +
    #40143780
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут пример последовательности Мюллера с коэф. из статьи Кулямина.
При бесконечной мантиссе получается таки 6, но иногда опять 100 :))
Код: C#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
/*

Стандартизация и тестирование реализаций
математических функций, работающих с числами с
плавающей точкой
В. В. Кулямин
Институт системного программирования РАН (ИСП РАН),
109004, Б. Коммунистическая, 25, Москва, Россия
E-mail: kuliamin@ispras.ru
*/
    static void RunMuller(BigRational x0, BigRational x1, int steps)
    {
        Console.WriteLine($" 0: {x0}");
        Console.WriteLine($" 1: {x1}");

        BigRational c111 = 111;
        BigRational c1130 = 1130;
        BigRational c3000 = 3000;

        for (int i = 2; i <= steps; i++)
        {
            BigRational x2 = c111 - (c1130 - c3000 / x0) / x1;

            double approx = (double)x2;
            Console.WriteLine($"{i,2}: >>>>{approx:F6}<<<<  ({x2})");

            x0 = x1;
            x1 = x2;
        }
    }
результаты
.NET 9 пример из Кулямина --- Сценарий 1 (Старт: 2 и -4) --- 0: 2 1: -4 2: >>>>18,500000<<<< (18 + 1/2) 3: >>>>9,378378<<<< (9 + 14/37) 4: >>>>7,801153<<<< (7 + 278/347) 5: >>>>7,154414<<<< (7 + 418/2707) . . . . 99: >>>>6,000000<<<< (6 + 1577721810442023610823457130565572459346412870218046009540557861328125/81664826359787052820062672571300097001570504462706488724837986255629281356547) 100: >>>>6,000000<<<< (6 + 7888609052210118054117285652827862296732064351090230047702789306640625/489988959736444127362399646251257712574995486122651802567073927074333549467407) --- Сценарий 2 (Старт: 11/2 и 61/11) --- 0: 5 + 1/2 1: 5 + 6/11 2: >>>>5,590164<<<< (5 + 36/61) 3: >>>>5,633431<<<< (5 + 216/341) 4: >>>>5,674649<<<< (5 + 1296/1921) 5: >>>>5,713329<<<< (5 + 7776/10901) 6: >>>>5,749121<<<< (5 + 46656/62281) 7: >>>>5,781811<<<< (5 + 279936/358061) 8: >>>>5,811314<<<< (5 + 1679616/2070241) 9: >>>>5,837657<<<< (5 + 10077696/12030821) 10: >>>>5,860952<<<< (5 + 60466176/70231801) . . . . 118: >>>>6,000000<<<< (5 + 66351011093336388265483390047725918911928587773465486323390644426653600903401882873197756416/66351011123429043646533950251725574264818077125623324576756084977277644584129364715238772041) 119: >>>>6,000000<<<< (5 + 398106066560018329592900340286355513471571526640792917940343866559921605420411297239186538496/398106066710481606498153141306353790236018973401582109207171069313041823824048706449391616621) 120: >>>>6,000000<<<< (5 + 2388636399360109977557402041718133080829429159844757507642063199359529632522467783435119230976/2388636400112426362083666046818124464651666393648703463976199213125130724540654829486144621601) --- Сценарий 3 от Жемини (Старт: 3/1 и 3/1) --- 0: 3 1: 3 2: >>>>67,666667<<<< (67 + 2/3) 3: >>>>109,078818<<<< (109 + 16/203) 4: >>>>101,046967<<<< (101 + 1040/22143) . . . . 40: >>>>100,000000<<<< (100 + 863549103651175062662801118594623/22396416573348264277715565509518477043673012308842323957813846506902924540383)
Program.cs
...
Изменено: 07.07.2026, 20:49:46 - tchingiz
Рейтинг: 0 / 0
Тестирование функций вещественной переменной. +
    #40143795
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
шаблон на сишарпе
nothing to do! # class is 'NumberAdapter<Double>' 0 2 1 -4 2 18,500000 18,5 3 9,378378 9,378378378378372 4 7,801153 7,801152737752091 5 7,154414 7,154414480974339 6 6,806785 6,806784736910842 7 6,592633 6,592632768516083 8 6,449466 6,449465930928838 9 6,348452 6,348452012239207 10 6,274438 6,274437898041683 11 6,218685 6,218684574004243 12 6,175658 6,175657670452935 13 6,139449 6,1394492929237146 14 6,068475 6,068474756960896 15 5,313341 5,313340680877218 16 -8,631298 -8,631298014827905 17 176,503875 176,50387495343017 18 102,628669 102,6286694076454 19 100,155046 100,15504592975981 20 100,009357 100,00935652464199 21 100,000565 100,00056474714142 22 100,000034 100,0000340550454 23 100,000002 100,00000205182243 24 100,000000 100,00000012353536
# class is 'NumberAdapter<BigRational>' 0 2 1 -4 2 18,500000 18 + 1/2 3 9,378378 9 + 14/37 4 7,801153 7 + 278/347 5 7,154414 7 + 418/2707 6 6,806785 6 + 15625/19367 7 6,592633 6 + 78125/131827 8 6,449466 6 + 390625/869087 9 6,348452 6 + 1953125/5605147 10 6,274439 6 + 9765625/35584007 11 6,218696 6 + 48828125/223269667 12 6,175837 6 + 244140625/1388446127 13 6,142359 6 + 1220703125/8574817387 14 6,115883 6 + 6103515625/52669607447 15 6,094739 6 + 30517578125/322121160307 16 6,077722 6 + 152587890625/1963244539967 17 6,063940 6 + 762939453125/11932055130427 18 6,052722 6 + 3814697265625/72355270235687 19 6,043552 6 + 19073486328125/437946318679747 20 6,036032 6 + 95367431640625/2646751398406607 21 6,029847 6 + 476837158203125/15975875822080267 22 6,024750 6 + 2384185791015625/96332092090684727 23 6,020540 6 + 11920928955078125/580376738335123987 24 6,017058 6 + 59604644775390625/3494181358965822047
mullerClass_01.zip
...
Изменено: 09.07.2026, 15:15:56 - tchingiz
Рейтинг: 0 / 0
Тестирование функций вещественной переменной. +
    #40143860
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2026.07.15 v 02 добавлен BigDecimal с фиксированной точкой. как предсказывала теория последовательность сходится к 100 # class is 'NumberAdapter<BigDecimal>' .... 82 6,024046 6,0240459429501867606219293525187623187539873648525871676048162110562164716256772765244439066631203 83 6,399159 6,3991592376456304116474392790926324594567246847041150136798004068269053902602158380434713607621882 84 12,237677 12,23767724689228334522910100113173748672262479889093785916092914256886858263620258502458568010379417 85 56,971086 56,97108590985049001596538004738247856745034561679106059623608912425469889764132043389883308800858924 86 95,468342 95,46834168237313429240328865576392618484504323990644218314142872011244445049311918292809925124562363 87 99,715194 99,71519405937827843158114282238927134437279770659672439935942985340707385457946627029351135173089772 88 99,982863 99,98286283540406344778384647494981820779209956256578005950007480848822510608981814833877936625204624 89 99,998972 99,99897159385972953211597406409113250407241604347980269580230051836496495591181380507583740695215925 90 99,999938 99,99993829499576244133698679948441232103742759729366260720977368591010585560211154522380279367538524 91 99,999996 99,99999629769739907595628946489154063492719254852305805283174414649891560096264746276826843478500699 92 100,000000 99,999999777861832612100953471829885131612520374330422449549787949612672411962763237364499946617815596 93 100,000000 99,99999998667170977170736804479366881480160058491238849036989021610229575878900751381928761962830969
mullerClass_02.zip
...
Изменено: 15.07.2026, 19:52:56 - tchingiz
Рейтинг: 0 / 0
Тестирование функций вещественной переменной. +
    #40143945
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В качестве тренировки тестирования функций вещественного аргумента
переделан пример вычисления длины меридиана (по лекциям Серапинаса, там две функции широта в метры от экватора и метры в широту)
с double в полиморфную форму для double и BigDecimal (https://www.researchgate.net/publication/385781889)
60 тестов показали совпадение старых методов и новых полиморфных.

test20.bd.txt -- полиморфное вычисления через BigDecimal
test20.d.txt -- старое через double
test20.p.txt -- полиморфное через double

---
Будет переделка кода под FMA (Fused Multiply-Add, или FMA) по стандарту IEEE 754)
Код: C++
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
     T X =   C0  * B_radians
            - C2  * ((dynamic)((T)2) * B_radians).Sin()
            + C4  * ((dynamic)((T)4) * B_radians).Sin()
            - C6  * ((dynamic)((T)6) * B_radians).Sin()
            + C8  * ((dynamic)((T)8) * B_radians).Sin()
      ;

     T B_radians = beta
               + D2  * ((dynamic)((T)2) * beta).Sin()
               + D4  * ((dynamic)((T)4) * beta).Sin()
               + D6  * ((dynamic)((T)6) * beta).Sin()
               + D8  * ((dynamic)((T)8) * beta).Sin();
а потом попытка поиска проблем по иеее754 с double
test20.bd.txt
test20.d.txt
test20.p.txt
mrdnLen_02.00.05.zip
...
Рейтинг: 0 / 0
Тестирование функций вещественной переменной. +
    #40143965
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попытка применить FMA (не смотря на рекомендации иеее754) для вычисления длин меридиана с блеском навернулась медным тазом.
После долгих вопрошаний БЛМ сошлись на том, что что бы была польза от ФМА, то не надо использовать функции и должно быть много выражений.

Исходный код
Код: C#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
    private double len_(double B_radians) {
      double X = C0  * B_radians
               - C2  * Math.Sin(2 * B_radians)
               + C4  * Math.Sin(4 * B_radians)
               - C6  * Math.Sin(6 * B_radians)
               + C8  * Math.Sin(8 * B_radians) ;
      return X;
    }
     private double latitude_(double X) {
      double beta = X / C0;
      double B_radians = beta
               + D2  * Math.Sin(2 * beta)
               + D4  * Math.Sin(4 * beta)
               + D6  * Math.Sin(6 * beta)
               + D8  * Math.Sin(8 * beta);
      return B_radians ;
    }
Код, переписанный мной под ФМА
Код: C#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
    private double lenFMA(double B_radians) {
      double sin2 = Math.Sin(2 * B_radians);
      double sin4 = Math.Sin(4 * B_radians);
      double sin6 = Math.Sin(6 * B_radians);
      double sin8 = Math.Sin(8 * B_radians);
      double X    = C0 *  B_radians;
      X = Math.FusedMultiplyAdd(-C2, sin2, X);
      X = Math.FusedMultiplyAdd( C4, sin4, X);
      X = Math.FusedMultiplyAdd(-C6, sin6, X);
      X = Math.FusedMultiplyAdd( C8, sin8, X);
      return X;
    }

    private  double latitudeFMA(double X) {
      double B_radians  = X / C0;
      double sin2       = Math.Sin(2 * B_radians);
      double sin4       = Math.Sin(4 * B_radians);
      double sin6       = Math.Sin(6 * B_radians);
      double sin8       = Math.Sin(8 * B_radians);
      B_radians = Math.FusedMultiplyAdd(D2, sin2, B_radians);
      B_radians = Math.FusedMultiplyAdd(D4, sin4, B_radians);
      B_radians = Math.FusedMultiplyAdd(D6, sin6, B_radians);
      B_radians = Math.FusedMultiplyAdd(D8, sin8, B_radians);
      return B_radians;
    }
Этот код на 3 млн тестов показал полное совпадение результатов (экономия на одном округлении оказалась незаметной) но работал на 30 процентов медленее (13 сек против 10 сек исходного кода).
жемини сказал, шо я тупой и переделал код по умному:
Код: C++
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
  private  double lenFMA_Fast(double B_radians) {
      double sinB = Math.Sin(B_radians);
      double cosB = Math.Cos(B_radians);
      double u = sinB * sinB;
      // Вычисление полинома по схеме Горнера с конца: ((((k4*u + k3)*u + k2)*u + k1)*u + k0)
      // (Коэффициенты k0..k4 вычисляются заранее из C0..C8)
      // double poly = Math.FusedMultiplyAdd(k4, u, k3);
      double poly = Math.FusedMultiplyAdd(k3, u, k2);
      poly = Math.FusedMultiplyAdd(poly, u, k1);
      poly = Math.FusedMultiplyAdd(poly, u, k0);
      return C0 * B_radians + sinB * cosB * poly;
    }
     // Предварительно пересчитанные коэффициенты K
     //  (вычисляются 1 раз в конструкторе):
     // K0 = D2 - D6;
     // K1 = 2*D4 - 4*D8;
     // K2 = 4*D6;
     // K3 = 8*D8;
     private  double latitudeFMA_Fast(double X) {
         double B    = X / C0;
         double twoB = 2.0 * B;

         // Всего ОДИН вызов тригонометрии вместо четырех!  // это блм написал, от меня -- гг))
         double sin2B = Math.Sin(twoB);
         double cos2B = Math.Cos(twoB);

         // Полиноминальная часть K3*t^3 + K2*t^2 + K1*t + K0 по схеме Горнера с FMA:
         double poly = Math.FusedMultiplyAdd(K3, cos2B, K2);
         poly = Math.FusedMultiplyAdd(poly, cos2B, K1);
         poly = Math.FusedMultiplyAdd(poly, cos2B, K0);

         // Итоговая широта B + sin(2B) * poly
         return Math.FusedMultiplyAdd(poly, sin2B, B);
     }
гм. быстрая версия стала работать на 15 процентов быстрее моей (11.5 сек против 13 сек и против 10сек исходной версии),
но зато неправильно
так шо с ФМА покончили надолго
...
Рейтинг: 0 / 0
Тестирование функций вещественной переменной. +
    #40143966
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Далее, по поводу Z3. Аналогичный случай был в городе Бердичеве.

Этот, не побоюсь этого слова((с) проф.Евстафьев) решатель работает с формулой, но не с исходным кодом.
Так шо, для поиска проблем в коде, оно бесполезно. Но, ПЕРЕД кодированием можно с формулами позаниматься через Z3,
убедиться, шо по формулам все хорошо, а потом - кодировать.
Но округления могут внести свои коррективы.
Как шел процесс доказательства монотоности (шо требует иеее754) не функции, а формулы, по которой вычисляет широту функция latitude.

КимиК3 начал бодро доказывать монотонность формулы, на 5 версии его код удалось откомилировать и выполнить.
Монотонность с блеском доказана.
UNSATISFIABLE Monotonicity proved: no counter-example exists.
прямой код
Спойлер
Код: C#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
using Microsoft.Z3;

class Program
{
    static void Main()
    {
        var ctx = new Context();
        var solver = ctx.MkSolver();

        var C0 = (ArithExpr)ctx.MkDiv(ctx.MkInt("63674491458"), ctx.MkInt("10000"));
        var D2 = (ArithExpr)ctx.MkDiv(ctx.MkInt("251882658"),   ctx.MkInt("100000000000"));
        var D4 = (ArithExpr)ctx.MkDiv(ctx.MkInt("370096"),      ctx.MkInt("100000000000"));
        var D6 = (ArithExpr)ctx.MkDiv(ctx.MkInt("745"),         ctx.MkInt("100000000000"));

        var sin = ctx.MkFuncDecl("sin", ctx.RealSort, ctx.RealSort);

        var u = ctx.MkRealConst("u");
        var v = ctx.MkRealConst("v");
        var zero = ctx.MkReal(0);
        var sinMax = (ArithExpr)ctx.MkDiv(ctx.MkInt("6"), ctx.MkInt("10000"));

        var sinMonotone = ctx.MkForall(
            new Expr[] { u, v },
            ctx.MkImplies(
                ctx.MkAnd(
                    ctx.MkGe(u, zero), ctx.MkLe(u, sinMax),
                    ctx.MkGe(v, zero), ctx.MkLe(v, sinMax),
                    ctx.MkLt(u, v)
                ),
                ctx.MkLt(
                    (ArithExpr)ctx.MkApp(sin, u),
                    (ArithExpr)ctx.MkApp(sin, v)
                )
            )
        );
        solver.Add(sinMonotone);

        solver.Add(ctx.MkEq(ctx.MkApp(sin, zero), zero));

        var X1 = (ArithExpr)ctx.MkRealConst("X1");
        var X2 = (ArithExpr)ctx.MkRealConst("X2");
        var Xmin = ctx.MkReal(0);
        var betaMax = (ArithExpr)ctx.MkDiv(ctx.MkInt("1"), ctx.MkInt("10000"));
        var Xmax = (ArithExpr)ctx.MkMul(C0, betaMax);

        solver.Add(ctx.MkGe(X1, Xmin), ctx.MkLe(X1, Xmax));
        solver.Add(ctx.MkGe(X2, Xmin), ctx.MkLe(X2, Xmax));
        solver.Add(ctx.MkLt(X1, X2));

        Func<ArithExpr, ArithExpr> Latitude = X =>
        {
            var beta = ctx.MkDiv(X, C0);
            var b2 = ctx.MkMul(ctx.MkReal(2), beta);
            var b4 = ctx.MkMul(ctx.MkReal(4), beta);
            var b6 = ctx.MkMul(ctx.MkReal(6), beta);

            return ctx.MkAdd(
                beta,
                ctx.MkMul(D2, (ArithExpr)ctx.MkApp(sin, b2)),
                ctx.MkMul(D4, (ArithExpr)ctx.MkApp(sin, b4)),
                ctx.MkMul(D6, (ArithExpr)ctx.MkApp(sin, b6))
            );
        };

        var B1 = Latitude(X1);
        var B2 = Latitude(X2);

        solver.Add(ctx.MkGe(B1, B2));

        var result = solver.Check();
        Console.WriteLine(result);

        if (result == Status.UNSATISFIABLE)
        {
            Console.WriteLine("Monotonicity proved: no counter-example exists.");
        }
        else if (result == Status.SATISFIABLE)
        {
            var m = solver.Model;
            Console.WriteLine("Counter-example found:");
            Console.WriteLine("  X1 = " + m.Evaluate(X1));
            Console.WriteLine("  X2 = " + m.Evaluate(X2));
            Console.WriteLine("  B1 = " + m.Evaluate(B1));
            Console.WriteLine("  B2 = " + m.Evaluate(B2));
        }
        else
        {
            Console.WriteLine("Z3 returned UNKNOWN.");
        }
    }
}
Мы там шото пообсуждали.
После чего китайца перемкнуло и он взял производную и начал искать когда производная равна 0, шо оказалось по его словам легче и
быстрее
Спойлер
Код: C#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
using Microsoft.Z3;

class Program
{
    static void Main()
    {
        var ctx = new Context();
        var solver = ctx.MkSolver();

        // all D2, D4, D6 : Real
        var D2 = (ArithExpr)ctx.MkDiv(ctx.MkInt("251882658"), ctx.MkInt("100000000000"));
        var D4 = (ArithExpr)ctx.MkDiv(ctx.MkInt("370096"),    ctx.MkInt("100000000000"));
        var D6 = (ArithExpr)ctx.MkDiv(ctx.MkInt("745"),       ctx.MkInt("100000000000"));

        // all c2, c4, c6 : Real :- c2 >= -1.0 /\ c2 <= 1.0
        //                      /\ c4 >= -1.0 /\ c4 <= 1.0
        //                      /\ c6 >= -1.0 /\ c6 <= 1.0
        var c2 = (ArithExpr)ctx.MkRealConst("c2");
        var c4 = (ArithExpr)ctx.MkRealConst("c4");
        var c6 = (ArithExpr)ctx.MkRealConst("c6");
        var m1 = (ArithExpr)ctx.MkUnaryMinus(ctx.MkReal(1));
        var p1 = ctx.MkReal(1);
        var zero = ctx.MkReal(0);

        solver.Add(ctx.MkGe(c2, m1), ctx.MkLe(c2, p1));
        solver.Add(ctx.MkGe(c4, m1), ctx.MkLe(c4, p1));
        solver.Add(ctx.MkGe(c6, m1), ctx.MkLe(c6, p1));

        // deriv = 1.0 + 2*D2*c2 + 4*D4*c4 + 6*D6*c6
        var term2 = ctx.MkMul(ctx.MkReal(2), ctx.MkMul(D2, c2));
        var term4 = ctx.MkMul(ctx.MkReal(4), ctx.MkMul(D4, c4));
        var term6 = ctx.MkMul(ctx.MkReal(6), ctx.MkMul(D6, c6));

        var deriv = ctx.MkAdd(p1, ctx.MkAdd(term2, ctx.MkAdd(term4, term6)));

        // exists c2, c4, c6 :- deriv <= 0.0
        solver.Add(ctx.MkLe(deriv, zero));

        var result = solver.Check();
        Console.WriteLine(result);

        if (result == Status.UNSATISFIABLE)
        {
            Console.WriteLine("Derivative > 0 proved for all cos in [-1, 1].");
            Console.WriteLine("Monotonicity proved on full meridian.");
        }
        else if (result == Status.SATISFIABLE)
        {
            var m = solver.Model;
            Console.WriteLine("Counter-example found:");
            Console.WriteLine("  c2 = " + m.Evaluate(c2));
            Console.WriteLine("  c4 = " + m.Evaluate(c4));
            Console.WriteLine("  c6 = " + m.Evaluate(c6));
            Console.WriteLine("  deriv = " + m.Evaluate(deriv));
        }
        else
        {
            Console.WriteLine("Z3 returned UNKNOWN.");
        }
    }
}
Формула должна работать монотонно, но про мою реализацию вопрос открыт.

Он сказал, шо для проверки реализаций надо использовать не Z3, а dReal. Но dReal
-- это питон. Этого ежа с ужом можно подружить, но мне лень.

...
Рейтинг: 0 / 0
Тестирование функций вещественной переменной. +
    #40143967
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
кста, жемини про производную намекал еще две недели назад
...
Рейтинг: 0 / 0
Тестирование функций вещественной переменной. +
    #40143995
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Очередной отрицательный результат.
Сравнение результатов тестов на основе случаных данных между double и BigDecimal не показало полезной разницы в обсуждаемом подсчете
длины меридиана. Из заметного результата - удалось нагреть воздух в комнате.
200000 попарных вычислений
Код: C#
1.
dev=arc.latitude(arc.len(B))-B;
время сумма отклонений выполнения от начальной точки 1598.0 10.587735494764985 Adapter<BigDecimal> 2.74 10.58773556551526 Adapter<double> 1.8 10.587730813946479 double
test_01.zip
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Тестирование и QA [игнор отключен] [закрыт для гостей] / Тестирование функций вещественной переменной. +
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]