МСС ресурс | Freeware | Open source | Кафедра МСС | Факультет |
Пакет |
|
ПРО ПАКЕТ | ПОПЕРЕДНІЙ КЛАС | НАСТУПНИЙ КЛАС |
multimap
|
+--result_manager
Даний клас призначено
для накопичення поточних результатів обчислень вигляду t, x1(t),...,xn(t),
(n>=0), їх обробки та зберігання. Клас зручно використовувати як вхідний
параметр для функцій моделювання, інтегрування тощо. В якості контейнера даних
використано multimap<T_index,valarray<T_data> >
.
Файл зберігається у текстовому форматі. Передбачено можливість редагування формату
файлу для забезпечення сумісності з табличними та графічними візуалізаторами.
Зокрема, для перегляду n-вимірних графіків, які записані за допомогою
даного класу, рекомендується використовувати JEDIgviewer.
У режимі відладки (DEBUG) здійснюється автоматичний контроль допустимості операцій.
У файлі mds.h
визначено наступні типи.
typedef double MDS_DEFAULT_TYPE;
typedef mds_exception_message MDS_DEFAULT_EXCEPTION;
typedef result_manager <MDS_DEFAULT_TYPE, MDS_DEFAULT_TYPE, MDS_DEFAULT_EXCEPTION>
ResultManager;
Члени класу | |
private string
|
autosave_comment Коментар, що буде записаний у файл при автозаписі. |
private string
|
autosave_file_name Ім'я файлу, куди будуть записуватися результати при автозаписі (порожнє ім'я блокує запис). |
private size_t |
cntDensity Внутрішня змінна (лічильник). |
size_t |
density Щільність поповнення контейнеру даних: ( density-1 ) елемент
ігнорується, а наступний запам'ятовується; якщо density = 1 (по
замовчуванню), то записуються всі дані, що поступають, якщо density
= 0 , то дані ігноруються. |
bool |
autosave Режим автозапису у файл: true - включено (по замовчуванню), false - відключено. Автозапис - це запуск функції зберігання даних у файл автоматично з деструктора. |
char |
separator Додатковий символ-роздільник між значеннями при записі у файл (по замовчуванню: ' ' - пробіл). Даний символ (якщо він не є пробілом) буде вставлений перед пробілом, який розділяє дані при записі у файл. |
char |
remark_mark Символ-роздільник, з якого починається коментар при записі у файл (по замовчуванню: ';' - крапка з комою). |
Конструктори |
result_manager <class Tind
= MDS_DEFAULT_TYPE, class Tdata = MDS_DEFAULT_TYPE, class EXCEPTION =
MDS_DEFAULT_EXCEPTION, class Cmp = less<Tind>, class A = allocator<pair<const
Tind, valarray<Tdata> > > > (const char* name
= "", const char* comm = "")
Параметри: name - ім'я файлу, куди будуть записуватися результати
при автозаписі (порожнє ім'я блокує запис), comm - коментар,
що буде записаний у файлі, створеному при автозаписі. Типи: Tind
- тип аргументу (індекс або ключ), Tdata - тип значень (які
будуть записані у вигляді valarray<Tdata >),
EXCEPTION - тип винятків, Cmp - порівняння,
A - виділення пам'яті. |
Функції-члени класу | |
int |
Add(const T_index& arg, const valarray<T_data>&
src, bool isReplace = false)
Поповнення контейнеру даних із src з індексом arg .
Реальне поповнення відбувається з урахуванням щільності density .
Параметр isReplace визначає чи дані будуть заміщені (true )
у випадку співпадання ключів, чи добавлені (false ). Повертає
0, якщо реально відбулося поповнення контейнеру. |
int |
|
int |
|
int |
|
result_manager& |
|
result_manager& |
|
result_manager& |
|
result_manager& |
|
void |
Modify(iterator first, iterator last,
Tdata fn(Tdata), const valarray<bool>& mask = valarray<bool>(size_t(0)))
Застосування функції fn до всіх елементів контейнеру, які
розташовані у інтервалі [first ,last ), але з
урахуванням маски: функція буде застосована тільки до тих елементів масиву,
індекси яких відповідають індексам з елементами true маски
mask (за замовчуванням - всі елементи). Зауваження: розмірність
маски не повинна перевищувати розмірність даних, до яких вона застосовується;
маска нульової розмірності означає застосування функції fn
до всіх елементів. |
void |
Modify(Tdata fn(Tdata), const valarray<bool>&
mask = valarray<bool>(size_t(0)))
Застосування функції fn до всіх елементів контейнеру, але
з урахуванням маски: функція буде застосована тільки до тих компонентів
масиву, індекси яких відповідають індексам з елементами true
маски mask (за замовчуванням - всі компоненти). Зауваження:
розмірність маски не повинна перевищувати розмірність даних, до яких вона
застосовується; маска нульової розмірності означає застосування функції
fn до всіх елементів. |
void |
Modify(iterator first, iterator last,
Tdata fn(const Tdata&), const valarray<bool>& mask = valarray<bool>(size_t(0)))
Застосування функції fn до всіх елементів контейнеру, які
розташовані у інтервалі [first ,last ), але з
урахуванням маски: функція буде застосована тільки до тих елементів масиву,
індекси яких відповідають індексам з елементами true маски
mask (за замовчуванням - всі елементи). Зауваження: розмірність
маски не повинна перевищувати розмірність даних, до яких вона застосовується;
маска нульової розмірності означає застосування функції fn
до всіх елементів. |
void |
Modify(Tdata fn(const Tdata&), const
valarray<bool>& mask = valarray<bool>(size_t(0)))
Застосування функції fn до всіх елементів контейнеру, але
з урахуванням маски: функція буде застосована тільки до тих компонентів
масиву, індекси яких відповідають індексам з елементами true
маски mask (за замовчуванням - всі компоненти). Зауваження:
розмірність маски не повинна перевищувати розмірність даних, до яких вона
застосовується; маска нульової розмірності означає застосування функції
fn до всіх елементів. |
int |
Save(const char* fName, const_iterator
first, const_iterator last, const valarray<bool>& mask = valarray<bool>(size_t(0)),
const char* comm = "", size_t dens = 1) const
Запис вмісту контейнера даних з інтервалу [first ,last )
у файл fName з коментарем comm та зі щільністю
запису dens . Запис ведеться з урахуванням маски mask :
будуть записані лише ті елементи, індекси яких відповідають індексам з
елементами true маски (по замовчуванню - всі елементи). Зауваження:
оскільки запис ведеться порціями {t,x1(t), x2(t),...,
xn(t)}, то маска повинна мати розмірність
не більшу за n+1, причому час t визначається самою першою
компонентою маски; маска нульової розмірності означає запис всіх елементів.
Замість цієї функції рекомендується використовувати режим автозапису.
Повертає 0 - ок, 1 - нульова щільність запису, 2 - неможливо відкрити
файл. |
int |
Save(const char* fName, const valarray<bool>&
mask = valarray<bool>(size_t(0)), const char* comm = "",
size_t dens = 1) const
Запис вмісту контейнера даних у файл fName з коментарем comm
та зі щільністю запису dens . Запис ведеться з урахуванням
маски mask : будуть записані лише ті елементи, індекси яких
відповідають індексам з елементами true маски (по замовчуванню
- всі елементи). Зауваження: оскільки запис ведеться порціями {t,x1(t),
x2(t),..., xn(t)}, то маска
повинна мати розмірність не більшу за n+1, причому час t
визначається самою першою компонентою маски; маска нульової розмірності
означає запис всіх елементів. Замість цієї функції рекомендується використовувати
режим автозапису. Повертає 0 - ок, 1 - нульова щільність запису, 2 - неможливо
відкрити файл. |
int |
Save(const char* fName, const_iterator
first, const_iterator last, const char* comm = "", size_t dens
= 1) const
Запис вмісту контейнера даних з інтервалу [first ,last )
у файл fName з коментарем comm та зі щільністю
запису dens . Замість цієї функції рекомендується використовувати
режим автозапису. Повертає 0 - ок, 1 - нульова щільність запису, 2 - неможливо
відкрити файл. |
int |
Save(const char* fName, const char*
comm = "", size_t dens = 1) const
Запис вмісту контейнера даних у файл fName з коментарем comm
та зі щільністю запису dens . Замість цієї функції
рекомендується використовувати режим автозапису. Повертає 0 - ок, 1 -
нульова щільність запису, 2 - неможливо відкрити файл. |
int |
Load(const char* fName, bool isReplace
= false)
Поповнення вмісту контейнера даних з файлу fName . Формат
даних (символи-роздільники та маркер коментарів) у файлі має відповідати
поточниму формату контейнера. Реальне поповнення відбувається з урахуванням
щільності density. Параметр isReplace визначає
чи дані будуть заміщені (true ) у випадку співпадання ключів,
чи добавлені (false ). Повертає 0 - відбулося поповнення контейнеру,
1 - не відбулося поповнення контейнеру, 2 - неможливо відкрити файл. |
int |
|
valarray<T_data> |
|
T_index |
|
valarray<T_data> |
|
T_index |
|
valarray<T_data> |
|
Наслідкові функції-члени класу multimap |
begin, clear, count, empty, end, equal_range, erase, find, insert, key_comp, lower_bound, max_size, rbegin, rend, size, swap, upper_bound, value_comp |
Опис |
Результати наукових обчислень, як правило, надзвичайно об’ємні. Чого лише коштує промоделювати одновимірну функцію із збереженням отриманих точок! Раніше для цього створювали ланцюги із масивів значень, використовуючи динамічне виділення пам’яті. Нічого поганого в цьому нема, але пани Степанов (Stepanov) та Страустрап (Stroustrup), всупереч анонсованій НАН України кризі програмології, запропонували цілий набір контейнерів, які значно спрощують написання подібних програм. За основу пропонується взяти асоціативний контейнер multimap <T_index, valarray<T_data> >, що забезпечує роботу із блоками даних вигляду t, x1(t),...,xn(t), (n>=0), де t - аргумент (або індекс) типу T_index, x - n-вимірний вектор значень, елементи якого мають тип T_data. За замовчуванням T_index та T_data мають тип double. Контейнер multimap є частиною STL – стандартної бібліотеки шаблонів і компілюється сучасними С++ компіляторами. Його специфікації читайте, наприклад, у "The C++ Programming Language, third edition" (B.Stroustrup).
Представлений клас інкапсулює основні дії, необхідність в яких виникає при маніпуляціях із результатами наукових обчислень: додавання результатів у контейнер (поповнення контейнеру), функціональну обробку, зберігання у файл та очищення контейнеру. Цей клас зручно використовувати в якості вхідного параметру для функцій моделювання, інтегрування тощо.
Конструктор передбачає задання імені файлу, куди будуть записані результати при автозаписі та необов'язкову стрічку з коментарем (зовсім не вказуйте аргументи, якщо не плануєте запис у файл). Автозапис – це запуск функції Save() із деструктора. Тобто достатньо ініціалізувати змінну типу result_manager із заданням імені файлу і функцію Save() вже не треба викликати безпосередньо, бо вона сама зробить свою справу в кінці області видимості змінної типу result_manager. Автозапис можна відмінити при необхідності за допомогою прапорця autosave=false. Конструктор без аргументів також блокує автозапис.
Поповнення контейнеру результатів можна проводити за допомогою однієї з функцій Add() (рекомендується) або використовуючи стандартні функції поповнення контейнеру multimap. Регулювання щільності поповнення контейнеру здійснюється за допомогою безпосереднього присвоювання значення параметру density (тільки для використання із функцією Add()). Нульове значення параметру density призводить до ігнорування всіх записів у контейнер, значення 1, навпаки, призводить до запису всіх значень. При цьому передбачається, що всі вектори значень, які додаються у контейнер мають однакову розмірність (дозволяється також нульова розмірність - для зберігання множини аргументів).
Функція Get(valarray<T_data>& x, const T_index& t) записує у x значення, що знаходяться у контейнері для аргументу t. Функція GetApproximation(valarray<T_data>& x, const T_index& t, size_t order = 1) робить те саме, але якщо для t значень не знайдено, то обчислюється апроксимація (з порядком order) та повертається різниця між найближчим аргументом, що знайдений у контейнері та тим, що вимагався. Крім того, передбачені функції, які безпосередньо повертають занчення (без використання буферу x): Get(const T_index& t) та GetApproximation(const T_index& t, size_t order = 1). Схожим чином працюють функції GetBangBang(). Треба при цьому слідкувати, щоб, по-перше, контейнер не був порожнім, а по-друге, щоб у контейнері ключі (тобто аргументи) не повторювалися. Інакше треба використовувати функції-члени класу multimap.
Ось типове використання цього класу.
ResultManager results("res.txt");
results.Add(t, v); //додали в контейнер змінну типу
valarray<double> з аргументом t
w = results.GetApproximation(t); //записали у змінну w типу
valarray<double> значення, отримані для аргументу t
В результаті буде автоматично створений файл res.txt, у якому будуть міститися дані, що були накопичені під час роботи програми.
Також можна явно використати функцію Save(), для запису всіх або частини даних у файл. Читання з файлу записаної інформації здійснюється за допомогою Load(). Сервісні функції Modify() призначені для перетворювання даних, які містяться в контейнері. Якщо, наприклад, є необхідність змінити кожну компоненту всіх елементів контейнеру на їхні косинуси, то це можна здійснити за допомогою функції Modify(cos); Якщо зміні підлягають тільки деякі компоненти, то необхідно використати маску (підставляючи true на місце тих компонентів, які необхідно змінити). Для простих перетворювань (розтягу та зсуву на константу) перевантажено відповідні оператори *=, /=, +=, -=.
Крім того, доцільно використовувати стандартні функції контейнеру multimap, такі як erase(), clear(), find(), size(), begin() тощо.
Декілька слів про файл збереження результатів. Перш за все, не варто гнатися за „бінарністю”. Приріст швидкодії мінімальний, зате втрачається кросплатформеність. Крім того, часто виникає необхідність безпосередньо зазирнути у такий файл. Отже доцільно робити його текстовим. На сьогодні існує велика кількість різноманітних табличних та графічних візуалізаторів, які передбачають задання вхідної інформації у текстовому файлі. Але формати розміщення текстової інформації у файлі не стандартизовані. Тому користувач сам повинен попіклуватися про те, щоб отриманий файл відповідав бажаному формату. Передбачається, що дані розміщуються блоками (аргумент та n значень, які йому відповідають) - кожен блок у окремій стрічці. Дані в середені блоку розділяються пробілами, але за допомогою змінної separator можна задавати додатковий символ-роздільник (наприклад, кому). Також дозволяються коментарі, які можна розташовувати на початку файлу. Кожна стрічка коментарів повинна починатися з деякого символа (маркера), який задається у remark_mark (за замовчуванням ';' - крапка з комою). Саме такий формат підтримує, зокрема, JEDIgviewer.
Приклад використання МДС знаходиться у файлі main.cpp у директорії mds_example. Додаткова інформація по використанню міститься в описі пакету.
Будь-ласка, надсилайте пропозиції, питання, зауваження: soft@unicyb.kiev.ua
Запрошуємо також до участі у самому проекті: надсилайте свої матеріали, які,
по-можливості, будуть виставлені на сайті (див. Для
авторів).
Кафедра Моделювання складних систем факультету кібернетики Київського
університету імені Тараса Шевченка
03127, Україна, Київ, просп. Глушкова 2, корп. 6, кафедра МСС тел.: (044) 259-05-31,
(044) 259-02-37, e-mail: garash@unicyb.kiev.ua
Всі права застережено.