Форум программистов, компьютерный форум CyberForum.ru

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

Войти
Регистрация
Восстановить пароль
 
vlad_light
4 / 4 / 0
Регистрация: 24.09.2012
Сообщений: 178
#1

Плохо работает ГСЧ - C++

20.01.2013, 03:03. Просмотров 432. Ответов 14
Метки нет (Все метки)

Подскажите, пожалуйста, как изменить программу, чтоб ГСЧ работал хорошо? Мне нужно, чтоб на каждой итерации у меня генерировался "хороший" вектор X, а оно мне генерирует пачками одинаковые. Как это можно обойти? И по коду подскажите -- где что поисправлять. Заранее весьма благодарен!
Кликните здесь для просмотра всего текста
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
// TPMVector.h
 
#pragma once
 
#include <vector>
 
class TPMVector 
{
public:
    TPMVector ();
    TPMVector (const TPMVector& copy);
    TPMVector& operator= (const TPMVector& copy);
 
    ~TPMVector ();
 
    std::vector<std::vector<int>> TPMvec;
    
    void initRandomVector (const int K, const int N);
};
// TPMVector.cpp
 
#include "TPMVector.h"
 
#include <cstdlib>
#include <ctime>
 
TPMVector::TPMVector ()
{
 
}
 
TPMVector::TPMVector (const TPMVector& copy)
{
    TPMvec = copy.TPMvec;
}
 
TPMVector& TPMVector::operator= (const TPMVector& copy)
{
    TPMvec = copy.TPMvec;
    return *this;
}
 
TPMVector::~TPMVector ()
{
 
}
 
void TPMVector::initRandomVector (int K, int N)
{
    srand ((unsigned int) time (NULL));
    const int LABEL = RAND_MAX / 2;
 
    TPMvec.reserve (K);
    TPMvec.clear ();
    
    for (int i = 0; i < K; ++i)
    {
        std::vector<int> random_vector;
        random_vector.reserve (N);
 
        for (int j = 0; j < N; ++j)
        {
            if (rand () > LABEL)
                random_vector.push_back (1);
            else
                random_vector.push_back (-1);
        }
 
        TPMvec.push_back (random_vector);
    }
}

Кликните здесь для просмотра всего текста
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
// TPM.h
 
#pragma once
 
#include "TPMVector.h"
 
int sign (const int x);
int g (const int x, const int L);
int theta (const int x);
 
int metric (const TPMVector& vec1, const TPMVector& vec2);
 
class TPM
{
private:
    int K, N, L;
    TPMVector Weights;
    std::vector<int> Sigma;
 
public:
    TPM ();
    TPM (const TPM& copy);
    TPM (const int K_value, const int N_value, const int L_value);
    TPM& operator= (const TPM& copy);
 
    ~TPM ();
 
    void initK (const int value);
    void initN (const int value);
    void initL (const int value);
 
    void initWeights ();
    void updateSigma (const TPMVector& random_vector);
    int TPMoutput () const;
    void updateWeights (const TPMVector& random_vector, const int received_bit);
    
    TPMVector returnWeights () const;
};
// TPM.cpp
 
#include "TPM.h"
 
#include <cstdlib>
#include <ctime>
 
int sign (const int x)
{
    if (x > 0)
        return 1;
 
    return -1;
}
 
int g (const int x, const int L)
{
    if (x > L || x < -L)
        return L * sign (x);
 
    return x;
}
 
int theta (const int x)
{
    if (x > 0)
        return 1;
 
    return 0;
}
 
int metric (const TPMVector& vec1, const TPMVector& vec2)
{
    int sum = 0;
 
    for (auto ITER1 = vec1.TPMvec.cbegin (), ITER2 = vec2.TPMvec.cbegin (); ITER1 != vec1.TPMvec.cend (); ++ITER1, ++ITER2)
        for (auto iter1 = ITER1->cbegin (), iter2 = ITER2->cbegin (); iter1 != ITER1->cend (); ++iter1, ++iter2)
            sum = sum + (*iter1 - *iter2) * (*iter1 - *iter2);
 
    return sum;
}
 
TPM::TPM ()
{
 
}
 
TPM::TPM (const TPM& copy)
{
    K = copy.K;
    N = copy.N;
    L = copy.L;
    Weights = copy.Weights;
    Sigma = copy.Sigma;
}
 
TPM::TPM (const int K_value, const int N_value, const int L_value)
{
    K = K_value;
    N = N_value;
    L = L_value;
}
 
TPM& TPM::operator= (const TPM& copy)
{
    K = copy.K;
    N = copy.N;
    L = copy.L;
    Weights = copy.Weights;
    Sigma = copy.Sigma;
 
    return *this;
}
 
TPM::~TPM ()
{
 
}
 
void TPM::initK (const int value)
{
    K = value;
}
 
void TPM::initN (const int value)
{
    N = value;
}
 
void TPM::initL (const int value)
{
    L = value;
}
 
void TPM::initWeights ()
{
    srand ((unsigned int) time (NULL));
 
    Weights.TPMvec.reserve (K);
    
    for (int i = 0; i < K; ++i)
    {
        std::vector<int> random_vector;
        random_vector.reserve (N);
 
        for (int j = 0; j < N; ++j)
            random_vector.push_back (rand () % (2 * L + 1) - L);
        
        Weights.TPMvec.push_back (random_vector);
    }
}
 
void TPM::updateSigma (const TPMVector& random_vector)
{
    Sigma.clear ();
 
    for (int i = 0; i < K; ++i)
    {
        int sum = 0;
 
        for (int j = 0; j < N; ++j)
            sum += Weights.TPMvec.at(i).at(j) * random_vector.TPMvec.at(i).at(j);
        
        Sigma.push_back (sign (sum));
    }
}
 
int TPM::TPMoutput () const
{
    int prod = 1;
 
    for (auto iter = Sigma.cbegin (); iter != Sigma.cend (); ++iter)
        prod *= *iter;
 
    return prod;
}
 
void TPM::updateWeights (const TPMVector& random_vector, const int received_bit)
{
    const int output_bit = TPMoutput ();
 
    if (output_bit == received_bit)
    {
        for (int i = 0; i < K; ++i)
        {
            const int THETA = theta (Sigma.at(i) * output_bit);
 
            for (int j = 0; j < N; ++j)
                Weights.TPMvec.at(i).at(j) = g (Weights.TPMvec.at(i).at(j) + random_vector.TPMvec.at(i).at(j) * THETA, L);
        }
    }
}
 
TPMVector TPM::returnWeights () const
{
    return Weights;
}

Кликните здесь для просмотра всего текста
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
// main.cpp
 
#include "TPM.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
 
int main ()
{
    int K = 3, N = 4, L = 100;
 
    TPM A (K,N,L), B (K,N,L);
 
    A.initWeights ();
    B.initWeights ();
 
    std::cout << "Iter\tDist" << std::endl;
 
 
    for (int i = 0; i < 10000; ++i)
    {
        TPMVector X;
        X.initRandomVector (K, N);
 
        A.updateSigma (X);
        B.updateSigma (X);
 
        const int TAU_A = A.TPMoutput ();
        const int TAU_B = B.TPMoutput ();
 
        A.updateWeights (X, TAU_B);
        B.updateWeights (X, TAU_A);
 
        std::cout << i << "\t" <<metric (A.returnWeights (), B.returnWeights ()) << std::endl;
    }
 
    std::cin.get ();
    return 0;
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.01.2013, 03:03
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Плохо работает ГСЧ (C++):

Функция fread плохо работает с типом string - C++
Всем доброго времени суток. У меня возникла проблема с чтением из файла. Я храню информацию в виде структуры. struct PC { string...

Почему не полностью работает программа шифрования? шифрует ок, а дешифрирует плохо, теряет последние 2 символа - C++
вот так. Помогите с проблемой. #include &lt;vcl&gt; #include &lt;conio&gt; #include &lt;iostream&gt; #include &lt;algorithm&gt; #include &lt;string&gt; ...

ГСЧ - C++
А подскажите пожалуйста, как сгенерировать числа от 10 до 1000000 ? и какой тип переменной использовать, long long?

ГСЧ в большом диапазоне - C++
rand()% ограничен диапазоном от 0 до ~ 32 000. Нужно ГСЧ в меняющемся диапазоне от 0 до 1 000 000. Подскажите, как это реализовать на...

ГСЧ, одинаковые значения - C++
Подскажите, почему при каждом запуске программы генератор случайных чисел выдает одни и те же значения? т.е. если при первом запуске он...

ГСЧ для равномерного распределения случайных чисел на заданном интервале - C++
Доброго всем времени суток. Мне нужно получить последовательность случайных чисел типа double равномерно распределённых на заданном...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
MrGluck
Модератор
Эксперт CЭксперт С++
7210 / 4376 / 638
Регистрация: 29.11.2010
Сообщений: 11,887
20.01.2013, 04:55 #2
Хороший ГСЧ - std::mt19937, очень хороший ГСЧ - std::random_device все это в #include <random> (треубется поддержка С++11)

Добавлено через 1 минуту
"хорошесть " в данном случае мерилась лишь в качестве разброса (само собой возрастает время выполнения запроса) Для твоей цели первого ГСЧ должно хватить с лихвой.
0x10
2460 / 1632 / 238
Регистрация: 24.11.2012
Сообщений: 4,015
20.01.2013, 06:52 #3
"Оно генерирует пачками одинаковые" потому что srand вызывается в цикле. Уберите вызов из initRandomVector и поместите где-нибудь снаружи.

C++
1
srand ((unsigned int) time (NULL));
time возвращает время в секундах. Очевидно, в одну секунду может быть создано несколько объектов. И тогда у них будет одинковый набор псевдослучайных чисел.
vlad_light
4 / 4 / 0
Регистрация: 24.09.2012
Сообщений: 178
20.01.2013, 16:18  [ТС] #4
я переписал файл main.cpp, следующим образом:
Кликните здесь для просмотра всего текста
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
// main.cpp
 
#include "TPM.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
 
int main ()
{
    int K = 2, N = 3, L = 20;
 
    TPM A (K,N,L), B (K,N,L);
 
    std::cout << "Num\tIter\tDist" << std::endl;
 
    srand ((unsigned int) time (NULL));
 
    for (int j = 0; j < 10; ++j)
    {
        A.initWeights ();
        B.initWeights ();
    
        int i;
 
        for (i = 0; i < 1000; ++i)
        {
            TPMVector X;
            X.initRandomVector (K, N);
 
            A.updateSigma (X);
            B.updateSigma (X);
 
            const int TAU_A = A.TPMoutput ();
            const int TAU_B = B.TPMoutput ();
 
            A.updateWeights (X, TAU_B);
            B.updateWeights (X, TAU_A);
        }
        
        std::cout << j << "\t" << i << "\t" << metric (A.returnWeights (), B.returnWeights ()) << std::endl;        
    }
 
    std::cin.get ();
    return 0;
}

Но при запуске, расстояние с каждой итерацией увеличивается (оно должно почти всегда быть равным 0 и это выполняется при одиночных запусках). Почему это происходит?
И с библиотекой <random> можете подсказать, а то я не разобрался, как ей пользоваться. Спасибо!
MrGluck
Модератор
Эксперт CЭксперт С++
7210 / 4376 / 638
Регистрация: 29.11.2010
Сообщений: 11,887
20.01.2013, 17:35 #5
Цитата Сообщение от vlad_light Посмотреть сообщение
с библиотекой <random> можете подсказать, а то я не разобрался, как ей пользоваться. Спасибо!
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <random>
#include <ctime>
#include <algorithm>
#include <iterator>
 
int main()
{
    const int N = 25;
    int A[N];
    // инициализируем ГСЧ std::mt19937 результатом работы ГСЧ std::random_device
     std::mt19937 gen { std::random_device()() };
    //std::mt19937 gen(time (0)); // или с помощью time
    std::uniform_int_distribution<int> uid(0, 99); // распределение
    std::generate(A, A + N, [&uid, &gen] { return uid(gen); } ); // с помощью спец. алгоритма из STL
    for (auto &x : A)
        x = uid(gen); // с помощью цикла (в данном случае цикл for_each, но можно и обычным)
    std::copy(A, A + N, std::ostream_iterator<int> (std::cout, " ") ); // копируем в поток std::ostream
    //for (auto &x : A)
    //    std::cout << x << " "; // или по обычному с помощью цикла
    std::cout << std::endl;
}
http://liveworkspace.org/code/3iy6N9

C++
1
std::vector<std::vector<int>>
Так делать не надо.
C++
1
std::vector<std::vector<int> >
vlad_light
4 / 4 / 0
Регистрация: 24.09.2012
Сообщений: 178
20.01.2013, 17:46  [ТС] #6
а как двумерный вектор сделать? Или его вообще не стоит использовать и заменить его на одномерный?
MrGluck
Модератор
Эксперт CЭксперт С++
7210 / 4376 / 638
Регистрация: 29.11.2010
Сообщений: 11,887
20.01.2013, 17:47 #7
vlad_light, вот пример с двумерным вектором:
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
#include <iostream>
#include <algorithm>
#include <iterator>
#include <random>
#include <cstddef>
#include <vector>
 
 
int main()
{
    std::size_t M, N;
    std::cin >> M >> N;
    std::vector <std::vector<int> > A (M, std::vector<int> (N));
    std::random_device rd;
    std::mt19937 gen (rd());
    std::uniform_int_distribution<int> uid (10, 99);
    auto print_v = [](const std::vector<int>& v)
    {
        std::copy(v.begin(), v.end(), std::ostream_iterator<int> (std::cout, " "));
        std::cout << std::endl;
    };
    std::cout << "Before:\n";
    for (auto &v : A)
    {
        std::generate(v.begin(), v.begin() + N, [&uid, &gen] { return uid(gen); } );
        print_v(v);
        std::sort(v.begin(), v.end());
    }
    std::cout << "\nAfter:\n";
    for (auto &v : A)
        print_v(v);
}
Все зависит от поставленной задачи. То же, что и когда следует использовать одномерный массив, а когда двумерный.
vlad_light
4 / 4 / 0
Регистрация: 24.09.2012
Сообщений: 178
20.01.2013, 17:48  [ТС] #8
C++
1
for (auto &x : A)
это называется лямбда? Я просто такое впервые вижу
MrGluck
Модератор
Эксперт CЭксперт С++
7210 / 4376 / 638
Регистрация: 29.11.2010
Сообщений: 11,887
20.01.2013, 17:51 #9
vlad_light, это for-цикл по коллекции (из последнего стандарта). Перебирает все элементы из A.
http://ru.wikipedia.org/wiki/C++11#F...86.D0.B8.D0.B8
vlad_light
4 / 4 / 0
Регистрация: 24.09.2012
Сообщений: 178
20.01.2013, 17:55  [ТС] #10
Или Вы имели ввиду, что нужно ставить отступ перед последней кавычкой, чтоб не спутать с ">>"?
MrGluck
Модератор
Эксперт CЭксперт С++
7210 / 4376 / 638
Регистрация: 29.11.2010
Сообщений: 11,887
20.01.2013, 17:58 #11
vlad_light, это я тоже имел ввиду.
0x10
2460 / 1632 / 238
Регистрация: 24.11.2012
Сообщений: 4,015
20.01.2013, 18:00 #12
vlad_light, он о пробеле. Но в итоге получается какая-то каша, ибо если используем 11 стандарт, то запись без пробела допустима. И раз уж возник такой вопрос: да, проще использовать одномерный вектор.
MrGluck
Модератор
Эксперт CЭксперт С++
7210 / 4376 / 638
Регистрация: 29.11.2010
Сообщений: 11,887
20.01.2013, 18:07 #13
0x10, допустимо то оно допустимо, но от лишнего пробела не умрешь, а вреда это точно не нанесет. Это был совет. В конце концов, вложенные контейнеры так читать легче.
0x10
20.01.2013, 18:10
  #14

Не по теме:

MrGluck, вообще если у нас шаред поинтер на контейнер шаред поинтеров контейнеров шаред поинтеров объектов, то спасают не столько пробелы, сколько typedef )

MrGluck
Модератор
Эксперт CЭксперт С++
7210 / 4376 / 638
Регистрация: 29.11.2010
Сообщений: 11,887
20.01.2013, 18:19 #15
0x10, пробелы в typedef, не?
Если не в С++0, то как раз такие вещи (подстановка typedef и неизвестная ошибка) и вызывали неодумевание.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.01.2013, 18:19
Привет! Вот еще темы с ответами:

ГСЧ для float из всего диапазона - C++
Ребят, подскажите, пожалуйста, как можно сгенерировать число типа float из всего диапазона данного типа? Причем, если получится NaN, +Inf,...

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

Плохо усваивается материал по С++ - C++
Что делать?Когда читаю в инете,в книжке материалы по c++,даже не только по ему,начинаю читать одно и то же предложение по 10 и больше...

Много макросов - это плохо? - C++
Здравствуйте. Скажите, нормально-ли, что в данном примере я использую большое количество макросов? class Field { #define HEIGHT...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
20.01.2013, 18:19
Ответ Создать тему
Опции темы

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