Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Ввод функции многих переменных


Автор: Shadowlord 7.6.2009, 10:42
Пишу программу для симпелекс метода минимизации функций многих переменных, вот алгоритм
http://sapr.mgsu.ru/biblio/optimiz/m7.htm
Так вот основная проблема как организовать ввод пользователем этой функции и потом проанализировать ее.  

Автор: xvr 8.6.2009, 16:25
Самый простой метод - забить функцию в программу.
Самый сложный метод - сделать интерпретатор (или JIT) для вычисления функции
Средний по сложности метод - обернуть функцию в специальный врапер, сгенерировать из этого отдельный С файл, откомпилировать его в виде динамической библиотеки, динамически загрузить к себе в программу

Автор: GoldFinch 8.6.2009, 17:39
если функция линейная - вводи ее коэффициенты

Автор: Shadowlord 10.6.2009, 07:46
функция может быть не линейной ,  в этом и есть основная проблема

Автор: Shadowlord 10.6.2009, 08:02
xvr,  можно чуть по подробней про средний метод 

Автор: kamre 10.6.2009, 09:24
Цитата(xvr @ 8.6.2009,  16:25)
Самый сложный метод - сделать интерпретатор (или JIT) для вычисления функции
Средний по сложности метод - обернуть функцию в специальный врапер, сгенерировать из этого отдельный С файл, откомпилировать его в виде динамической библиотеки, динамически загрузить к себе в программу

Почему интерпретатор (без всяких там JIT) самый сложный? Мне кажется это достаточно стандартная задачка, что-то вроде калькулятора.
А с генерацией файла, компиляцией и динамической загрузкой - это какой-то "извращенный" способ smile Это ж компилятор с собой придется таскать.

Автор: xvr 10.6.2009, 10:19
Цитата(Shadowlord @ 10.6.2009,  08:02)
xvr,  можно чуть по подробней про средний метод

Можно.
Например, пользователь вводит функцию в файле в таком виде:
Код

x,y,z
x*x+3.123*pow(y,3)+z
Первая строка - список переменных, вторая - собственно формула
Система генерит файл следующего содержания (wrap.cpp)
Код

#include <math.h>
extern "C" double user_func(double* _args)
{
 // Эта часть генерится из описания переменных
 double x=_args[0];
 double y=_args[1];
 double z=_args[2];
 // А это собственно вычисление
 return x*x+3.123*pow(y,3)+z;
}
Далее вызывается компилятор, 
  •  VC: cl /LD wrap.cpp 
  •  gcc: g++ -shared wrap.cpp -o wrap.so
  •  mingw: g++ -mdll wrap.cpp -o wrap.dll
Далее в своей программе полученная библиотека загружается и извлекается адрес функции user_func (см LoadLibrary, GetProcAddress для Windows, или dlopen,dlsym для Linux)
Т.к. прототип функции известен и фиксирован, то ее можно вызвать одним и тем же способом, вне зависимости от того, что в нее напишет пользователь

kamre:
Цитата

Почему интерпретатор (без всяких там JIT) самый сложный? Мне кажется это достаточно стандартная задачка, что-то вроде калькулятора.
Если есть готовый и скорость его работы устраивает, то милости просим  smile А вот писать специально для этого свой собственный явно не стоит (если конечно ты не съел собаку на написании компиляторов, и способен написать еще один даже не просыпаясь  smile )
Цитата

А с генерацией файла, компиляцией и динамической загрузкой - это какой-то "извращенный" способ smile
Нормальный способ, некоторые умудряются даже коммерческие продукты так делать  smile 
Цитата

 Это ж компилятор с собой придется таскать.
Да. 
Пример - Xilinx, ISE (среда программирования для их FPGA/CPLD), ихний симулятор (симулирует программы на Verilog & VHDL). Бесплатная и коммерческая версия отличаются только файлом лицензии. Симулятор преобразует исходный код в программу на C++, и компилирует ее вместе со своими библиотеками в exe (gcc входит в состав дистрибутива ISE). Полученный exe запускают под оболочкой симулятора.


Автор: Shadowlord 13.6.2009, 14:30
Вот нашел Парсер математических выражений (http://www.rsdn.ru/article/files/Classes/tparser.xml)
выдает ошибку
Код

Error    6    error C2668: 'exp' : ambiguous call to overloaded function    c:\parser.cpp    329

вот строка на которую ругается
Код

 temp = CreateNode((double)exp(1));

Не могу понять в чем проблема

Автор: xvr 13.6.2009, 16:35
Проблема в функции exp из math.h. Видимо где то нашлась еще одна  smile 
Напишите так
Код

 temp = CreateNode((double)exp(1.0));

Автор: Shadowlord 13.6.2009, 16:55
Вот еще вопрос 
я создал массив 
Код

array <double> ^X0;



Запомнил его из грида 
Код

 X0=gcnew array<double>(n);
                 for(int j=0; j<n;j++)
                                
                     X0[j]=Convert::ToSingle(dataGridView1->Rows[0]->Cells[j]->Value);

Хочу запихать его в парсер как  значение переменных а он мне говорит что типы не совпадают 
Код

Error    6    error C2664: 'double TParser::Evaluate(double *)' : cannot convert parameter 1 from 'cli::array<Type> ^' to 'double *'        214

как его привести к double *

Автор: xvr 13.6.2009, 21:51
Правильно говорит - массив должен быть обычный (double*), а не array и уж тем более не .net'овский указатель.
Делайте так
Код

double* X0;
 X0=new double[n];
                 for(int j=0; j<n;j++)
                                
                     X0[j]=Convert::ToSingle(dataGridView1->Rows[0]->Cells[j]->Value);
не забудьте позвать в конце delete[] X0;

Автор: Shadowlord 14.6.2009, 16:33
Еще один  вопрос, для расчетов нужно хранить вершины симплекса и их координаты являются значениями переменных по которым считается  функция. Я хочу использовать для этого динамический двумерный массив,  строка набор координат вершин, что б потом построчно скармливать их парсеру и  находить значение в каждой из вершин. 
Так вот я не могу описать этот самый масивв(если не ошибаюсь должен получится массив указателе )

Добавлено через 11 минут и 6 секунд
сделал так вроде каботает
Код

double** X;
X=new double*[n+1]; 
for(int i=0;i<n+1;i++) 
X[i]=new double[i];

Автор: xvr 14.6.2009, 16:56
В строке в new double[] нужно указать размер массива по 2му измерению (пусть будет k), а не i
Код

double** X;
X=new double*[n+1]; 
for(int i=0;i<n+1;i++) 
X[i]=new double[k]; // <<<

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)