Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
J5
25 / 25 / 6
Регистрация: 22.12.2013
Сообщений: 82
#1

Передача в функцию двумерного контейнера - C++

15.06.2014, 12:06. Просмотров 535. Ответов 4
Метки нет (Все метки)

Возникает ошибка при передачи в функцию minimuze двумерного вектора прошу показать правильный вариант. Заранее благодарю.

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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
#include <iostream>
#include <cmath>
#include <windows.h>
#include <vector>
using namespace std;
double f(double * P);
void grad(double * P, double * V);
double g(double t, double * A, double * V);
long min(long x, long y);
long max(long x, long y);
void minimize1D(double x, double y, double A, double B, double * P, double * V, double eps_x, double eps_y);
void cdm_gs(double* P, double * A, double* B, double eps_x, double eps_y);
void processGrid(vector<vector<double> > Lmins, vector<double> Ymins, double * Gmin, double ymin, double * A, double * B, double eps_x, double eps_y, long * M);
void minimuze(vector <vector<double> > Lmins, vector<double> Ymins, double * Gmin, double ymin, double * A, double * B, double eps_x, double eps_y);
const int n=2;//размерность задачи
int main(){
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    vector<vector<double> > P(n);
    vector <double> Ymins();
    double Gmin[n];
    double ymin;
    double eps;
    double A[n];
    double B[n];
    cin>>eps;
    cout<<"введите значения границ графика"<<endl;
    for(int i=0;i<n;i++){
            cout<<"введите значения A"<<endl;
            cin>>A[i];
            cout<<"введите значения B"<<endl;
            cin>>B[i];
    }
    minimuze(P, Ymins, Gmin, ymin, A, B, eps, eps);
    system("pause");
    return 0;
}
double f(double * P){//заданная функция f от n переменных для которой будут искаться локальные и глобальный минимумы
       return 4-(sin(3.1415*P[0])+1)*(sin(3.1415*P[1])+1);//P - массив из n чисел, точка в которой необходимо вычислить значение функции
}
/*V - массив из n чисел, в который будет записан результат - градиент функции f, т.е. значения n частных производных
   P - массив из n чисел, точка в которой необходимо вычислить градиент функции*/
void grad(double * P, double * V){
     double x,y;
     x=P[0];
     y=P[1];
     V[0]=-(sin(3.1415*y)+1)*cos(3.1415*x)*3.1415;//Проихводная по X
     V[1]=-(sin(3.1415*x)+1)*cos(3.1415*y)*3.1415;//Проихводная по Y
}
/*   t - смещение относительно начала луча.
     A - точка начала луча (массив из n чисел).
     V - вектор направления луча (массив из n чисел)
*/
double g(double t, double * A, double * V){//значения функции f вдоль луча A - t*V, t >= 0. Эта функция необходима для метода градиентного спуска
       double P[n];
       for(int i=0;i<n;i++) P[i]=A[i]-t*V[i];
       return f(P);
}
//функция для выбора минимума из двух целых чисел
long min(long x, long y){
               if(x>y) return y;
               else return x;
}
//функция для выбора максимума из двух целых чисел
long max(long x, long y){
               if(x>y) return x;
               else return y;
}
//процедура определяет точку минимума (x) и минимум (y) унимодальной функции g(x, P, V) = f(P - x*V) с погрешностями eps_x и eps_y на [A, B]
/* Используется метод парабол. Реультат заносится в переменные x и y.
     x - переменная, в которую будет записана точка минимума.
     y - переменная, в которую будет записанj значение минимума.
     A - нижняя граница отрезка на котором ищется минимум.
     B - верхняя граница отрезка на котором ищется минимум.
     P - точка начала луча (массив из n чисел).
     V - вектор направления луча (массив из n чисел).
     eps_x - требуемая точность по x.
     eps_y - требуемая точность по y.*/
void minimize1D(double x, double y, double A, double B, double * P, double * V, double eps_x, double eps_y){
       double x1,x2,x3,y1,y2,y3;
       x1=A;
       x2=0.5*(A+B);
       x3=B;
       y1=g(x1,P,V);
       y2=g(x2,P,V);
       y3=g(x3,P,V);
       if((B-A)<eps_x){//если отрезок слишко мал (меньше точности)
                     x=x2;
                     y=y2;
                     return;
       }
       double y12,y31,y23;//ищем вершину параболы, проходящей через три точки: (x1, y1), (x2, y2) и (x3, y3)
       y12=y1-y2;
       y31=y3-y1;
       y23=y2-y3;
       x=(x3*x3*y12+x1*x1*y23+x2*x2*y31)/(2*(x3*y12+x1*y23+x2*y31));
       y=g(x,P,V);
       while((abs(x2-x)>eps_x) || (abs(y2-y)>eps_y)){//цикл пока не достигнута заданная точность
                               if((x < x1) || (x > x3)){//вершина за пределами отрезка
                               x=x2;
                               y=y2;
                               return;
                               }//в зависимости от расположения точки x относительно точки x2 нужно изменить наши точки
                               if(x<x2){//если x справа от x2
                                        x3=x2;
                                        x2=x;
                                        y2=g(x2, P, V);//расчитываем значения функции в изменившихся точках
                                        y3=g(x3, P, V);
                               }
                               else{
                               x1=x2;
                               x2=x;
                               y1=g(x1, P, V);//расчитываем значения функции в изменившихся точках
                               y2=g(x2, P, V);
                               }
                               y12 = y1-y2;//Ищем вершину параболы, проходящей через три точки: (x1, y1), (x2, y2) и (x3, y3)
                               y31 = y3-y1;
                               y23 = y2-y3;
                               x=(x3*x3*y12+x1*x1*y23+x2*x2*y31)/(2*(x3*y12+x1*y23+x2*y31));
                               y=g(x,P,V);
       }
}
/*Процедура для минимизации унимодальной функции n-переменных в n-мерном прямоугольнике.
 Используется метод градиентного спуска.
     P - переменная, в которую будет записана точка минимума (массив из n чисел).
     A, B - две противоположные вершины n-мерного прямоугольника (массивы из n чисел).
     eps_x - точность с которой должно быть вычислено значение аргумента.
     eps_y - точность с которой должно быть вычислено значение минимума.*/
void cdm_gs(double * P, double * A, double * B, double eps_x, double eps_y){
     double V[n];
     double t, t_max, y, y_prev, t_prev, s, w;
     for(int i=0;i<n;i++) P[i]=(A[i]+B[i])/2;//вычисляем начальную точку (центр n-мерного прямоугольника)
     y=1e+100;
     t=1e+100;//основной цикл
     do{
                grad(V,P);//записываем в V градиент функции f в точке P
                s=0;
                for(int i=0;i<n;i++) s=s+pow(V[i],2);
                s=sqrt(s);
                t_max=1e+100;//Вопрос
                for(int i=0;i<n;i++){
                        w=(A[i]-P[i])/-V[i];
                        if((w>(-eps_x/s)) && (t_max>w)) t_max = w;
                        w=(B[i]-P[i])/-V[i];
                        if((w>(-eps_x/s)) && (t_max>w)) t_max=w;
                }
                y_prev=y;
                t_prev=t;
                minimize1D(t, y, 0, t_max, P, V, eps_x/s, eps_y/3);
                for(int i=0;i<n;i++) P[i]=P[i]-t*V[i];//вычисляем новую точку
     }while((abs(y-y_prev)>eps_y/3) || (abs(t - t_prev)>eps_x/s));//продолжаем цикл пока не будет достигнута заданная точность
}
/*Поиск локального и глобальных минимумов при заданном разбиении.
    Lmins - двумерный массив, в который будут записаны координаты точек минимумов.
    Ymins - массив, в который будут записаны значения минимумов.
    Gmin - массив, в который будут записаны координаты точки глобального минимума.
    ymin - переменная, в которую будет записано значение глобального минимума.
    A - нижние границы области (массив из n чисел).
    B - верхние границы области (массив из n чисел).
    eps_x - точность с которой должны быть вычислены значения аргументов.
    eps_y - точность с которой должно быть вычислено значение минимума.
    M - количество частей разбиения по каждому измерению (массив из n чисел).*/
void processGrid(vector <vector<double> > Lmins, vector<double> Ymins, double * Gmin, double ymin, double * A, double * B, double eps_x, double eps_y, long * M){
     long totalM;//общее число элементов в массиве значений фукнкции
     long J[n];//счётчики цикла
     double P[n];//текущая точка
     double Pitches[n];//смещения в массиве
     long num_min=0;//число минимумов
     ymin=1E+100;
     totalM=1;
     for(int i=0;i<n;i++){
             J[i]=0;//сбрасываем счётчики цикла
             P[i]=A[i];//начинаем в точке A
             totalM = totalM *(M[i] + 1);//при разбиении на M частей получается M + 1 точек
     }
     vector<double> YP(totalM);//массив значений функции
     Pitches[0] = 1;
     for(int i=1;i<n;i++) Pitches[i]=Pitches[i-1]*(M[i-1]+1);
     for(int i=0;i<totalM;i++){
             YP[i]=f(P);//цикл для расчёта значений функции в узлах сетки
             for(int k=0;k<n;k++){//увеличиваем счётчики и сдвигаем точку для перехода к следующей итерации
                     J[k]=J[k]+1;
                     P[k]=P[k]+(B[k]-A[k])/M[k];
                     if(J[k]<=M[k]) break;
                     J[k]=0;
                     P[k]=A[k];
             }
     }
     for(int i=0;i<n;i++) J[i]=0;//сбрасываем счётчики цикла
     bool strict, wrong;//значения проверки условий (хотя бы одно из неравенств строгое, хотя бы одно из неравенств невыполнено)
     double y;
     strict=wrong=false;
     long r;
     long D[n];//счётчики цикла для перебора соседних точек
     for(int i=0;i<totalM;i++){
             y=YP[i];
             for(int k=0;k<n;k++) D[k]=max(0,J[k]-1);
             for(long q=0;q<pow(3.0,n);q++){
                     r=0;
                     for(int k=0;k<n;k++) r+=(long)(D[k]*Pitches[k]);//вычисляем положение соседней точки в массиве
                     if(y>YP[r]){//если хотя бы одно из неравенств не выполняется то сразу выходим из цикла
                                 wrong=true;
                                 break;
                     }
                     else strict=true;
                     for(int k=0;k<n;k++){
                             D[i]=D[k]+1;//увеличиваем счётчики для перехода к следующей итерации
                             if(D[k]<=min(M[k],J[k]+1)) break;
                             D[k]=max(0,J[k]-1);
                     }
             }
             if((!wrong) && (strict)){
                         double Ai[n];
                         double Bi[n];
                         for(int k=0;k<n;k++){
                                 Ai[k]=A[k]+max(0,J[k]-1)*(B[k]-A[k])/M[k];//рассчитываем границы n-мерного параллелограмма
                                 Bi[k]=A[k]+min(M[k],J[k]+1)*(B[k]-A[k])/M[k];
                         }
                         double Pmin[n];
                         cdm_gs(Pmin, Ai, Bi, eps_x, eps_y);//минимизируем функцию на текущем n-мерном параллелограмме
                         for(int i=0;i<n;++i) Lmins[i].resize(num_min+1);//добавляем все точки минимума в общий массив
                         Ymins.resize(num_min+1);
                         Ymins[num_min]=f(Pmin);
                         for(int k=0;k<n;k++){
                                 Lmins[k][num_min]=Pmin[k];
                                 if(Ymins[num_min]<ymin) Gmin[k]=Pmin[k];
                         }
                         if(Ymins[num_min]<ymin) ymin=Ymins[num_min];
                         ++num_min;
     }
     for(int k=0;k<0;k++){//увеличиваем счётчики для перехода к следующей итерации
             ++J[k];
             if(J[k]<=M[k]) break;
             J[k]=0;
     }
     }
}
/*   Поиск локального и глобальных минимумов.
     Lmins - двумерный массив, в который будут записаны координаты точек минимумов.
     Ymins - массив, в который будут записаны значения минимумов.
     Gmin - массив, в который будут записаны координаты точки глобального минимума.
     ymin - переменная, в которую будет записано значение глобального минимума.
     A - нижние границы области (массив из n чисел).
     B - верхние границы области (массив из n чисел).
     eps_x - точность с которой должны быть вычислены значения аргументов.
     eps_y - точность с которой должно быть вычислено значение минимума.*/                       
void minimuze(vector <vector<double> > Lmins, vector <double> Ymins, double * Gmin, double ymin, double * A, double * B, double eps_x, double eps_y){
     double ymin_prev;
     long Mmax[n];
     long M[n];
     for(int i=0;i<n;i++){
             Mmax[i]= (int)(((B[i]-A[i])/(2*eps_x)) + 1);
             M[i]=(int)(((B[1]-A[1])/(30*eps_x)) + 1);
     }
     ymin_prev=1E+100;
     processGrid(Lmins, Ymins, Gmin, ymin, A, B, eps_x, eps_y, M);
     while(abs(ymin-ymin_prev)>2*eps_y){
     for(int i=0;i<n;i++) M[i]=2*M[i]+1;
     for(int i=0;i<n;i++) if(M[i]>=Mmax[i]){
             cout<<"Уменьшить EpsX";
             return;
     }
     ymin_prev = ymin;
     processGrid(Lmins, Ymins, Gmin, ymin, A, B, eps_x, eps_y, M);
     }
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.06.2014, 12:06
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Передача в функцию двумерного контейнера (C++):

Передача контейнера set в функцию - C++
Всем здравствуйте! Мне нужно написать функцию которая будет выводить всю информацию которая хранится в контейнере set. Пробовал передавать...

Передача двумерного массива в функцию - C++
Доброго времени суток. Как можно передать двумерный массив в функцию? Допустим есть функция: void filingMatrix(??). Пробовал сделать: ...

Передача двумерного массива в функцию - C++
Доброго времени суток, форумчане. Столкнулся с проблемой передачи двумерного массива (матрицы) по указателю в функцию. Подскажите?...

Передача двумерного массива в функцию - C++
Здравствуйте! Написала код для передачи двумерного массива в функцию: #include &lt;iostream&gt; #include &lt;locale.h&gt; #include...

Передача двумерного массива в функцию. - C++
Требуется написать функцию которая бы слагала и умножала матрицы. Для этого Я завел двумерный динамический массив, а вот с передачей его в...

Передача в функцию двумерного массива - C++
Вводится две квадратные матрицы разного размера, посчитать сумму модулей отрицательных элементов каждой матрицы, и среднее значение 2-х...

4
SlavaSSU
216 / 161 / 45
Регистрация: 17.07.2012
Сообщений: 587
15.06.2014, 12:16 #2
не помешало бы почаще нажимать кнопки ентер и пробел)))
0
Croessmah
Ушел
Эксперт CЭксперт С++
13557 / 7707 / 872
Регистрация: 27.09.2012
Сообщений: 18,996
Записей в блоге: 3
Завершенные тесты: 1
15.06.2014, 12:19 #3
Цитата Сообщение от J5 Посмотреть сообщение
Возникает ошибка при передачи в функцию minimuze двумерного вектора
какая? че пишет? сколько стоит?
0
J5
25 / 25 / 6
Регистрация: 22.12.2013
Сообщений: 82
15.06.2014, 12:26  [ТС] #4
34 D:\Чтиво\Матан\Работа\Минимизация.cpp conversion from `std::vector<double, std::allocator<double> > (*)()' to non-scalar type `std::vector<double, std::allocator<double> >' requested

Добавлено через 1 минуту
SlavaSSU Это дело вкуса, чудак)
0
Croessmah
Ушел
Эксперт CЭксперт С++
13557 / 7707 / 872
Регистрация: 27.09.2012
Сообщений: 18,996
Записей в блоге: 3
Завершенные тесты: 1
15.06.2014, 12:27 #5
C++
1
vector <double> Ymins();//<-- Вот это объявление функции, а не объявление вектора.
уберите скобочки
1
15.06.2014, 12:27
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.06.2014, 12:27
Привет! Вот еще темы с ответами:

Передача двумерного массива в функцию - C++
Как я знаю, имя массива и указателя тождественны в С++. Из этого следует, что можно инициализировать указатель, а работать с ним, как с...

Передача двумерного массива в функцию - C++
Доброго времени суток, возникла проблема с передачей двумерного массива в с++. По условию необходимо подсчитать норму матрицы, для этого...

Передача в функцию двумерного массива - C++
Доброго времени суток. Есть двумерный массив, размерностью n на m. Нужно передать его в качестве параметра в функцию 1) обычным способом 2)...

Передача двумерного массива в функцию - C++
Не нашел в поиске, как правильно передавать в функцию в качестве параметра двумерный массив произвольного размера, чтобы в функции была...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.