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

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

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

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

20.01.2013, 03:03. Просмотров 425. Ответов 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;
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
MrGluck
Ворчун
Эксперт CЭксперт С++
6616 / 3807 / 496
Регистрация: 29.11.2010
Сообщений: 10,046
20.01.2013, 04:55     Плохо работает ГСЧ #2
Хороший ГСЧ - std::mt19937, очень хороший ГСЧ - std::random_device все это в #include <random> (треубется поддержка С++11)

Добавлено через 1 минуту
"хорошесть " в данном случае мерилась лишь в качестве разброса (само собой возрастает время выполнения запроса) Для твоей цели первого ГСЧ должно хватить с лихвой.
0x10
2454 / 1626 / 238
Регистрация: 24.11.2012
Сообщений: 4,001
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Эксперт С++
6616 / 3807 / 496
Регистрация: 29.11.2010
Сообщений: 10,046
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Эксперт С++
6616 / 3807 / 496
Регистрация: 29.11.2010
Сообщений: 10,046
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Эксперт С++
6616 / 3807 / 496
Регистрация: 29.11.2010
Сообщений: 10,046
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Эксперт С++
6616 / 3807 / 496
Регистрация: 29.11.2010
Сообщений: 10,046
20.01.2013, 17:58     Плохо работает ГСЧ #11
vlad_light, это я тоже имел ввиду.
0x10
2454 / 1626 / 238
Регистрация: 24.11.2012
Сообщений: 4,001
20.01.2013, 18:00     Плохо работает ГСЧ #12
vlad_light, он о пробеле. Но в итоге получается какая-то каша, ибо если используем 11 стандарт, то запись без пробела допустима. И раз уж возник такой вопрос: да, проще использовать одномерный вектор.
MrGluck
Ворчун
Эксперт CЭксперт С++
6616 / 3807 / 496
Регистрация: 29.11.2010
Сообщений: 10,046
20.01.2013, 18:07     Плохо работает ГСЧ #13
0x10, допустимо то оно допустимо, но от лишнего пробела не умрешь, а вреда это точно не нанесет. Это был совет. В конце концов, вложенные контейнеры так читать легче.
0x10
20.01.2013, 18:10
  #14

Не по теме:

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

MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.01.2013, 18:19     Плохо работает ГСЧ
Еще ссылки по теме:

C++ Плохо усваиваю циклы
Плохо усваивается материал по С++ C++
Функция fread плохо работает с типом string C++
C++ Насколько плохо написан код?

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

Или воспользуйтесь поиском по форуму:
MrGluck
Ворчун
Эксперт CЭксперт С++
6616 / 3807 / 496
Регистрация: 29.11.2010
Сообщений: 10,046
20.01.2013, 18:19     Плохо работает ГСЧ #15
0x10, пробелы в typedef, не?
Если не в С++0, то как раз такие вещи (подстановка typedef и неизвестная ошибка) и вызывали неодумевание.
Yandex
Объявления
20.01.2013, 18:19     Плохо работает ГСЧ
Ответ Создать тему
Опции темы

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