Атрибути та методи
Останнє оновлення 2026-06-16 | Редагувати цю сторінку
Приблизний час: 50 хвилин
Огляд
Питання
- Як зберігати інформацію в об’єктах GAP?
Цілі
- Оголошення атрибута
- Встановлення методу
- Розуміння вибору методу
- Використання інструментів для налагодження
Яка функція швидше?
Спробуйте багаторазово обчислити AvgOrdOfGroup(M11) та
AvgOrdOfCollection(M11), і порівняти час виконання. Зробіть
це для нової копії M11 і для тієї, для якої цей параметр
щойно було обчислено. Що ви помітили?
Звичайно, для будь-якої даної групи середній порядок її елементів
потрібно обчислити лише один раз, оскільки наступного разу повертається
те ж саме значення. Однак, як ми бачимо з часу виконання нижче, кожен
новий виклик AvgOrdOfGroup повторюватиме те саме обчислення
знову, дещо змінюючи час виконання:
ВИВІД
Alt( [ 1 .. 10 ] )
ВИВІД
2587393/259200
8226
2587393/259200
8118
В останньому прикладі група ми не створили іншу копію
AlternatingGroup(10), але результат обчислення не було
збережено в A.
Якщо потрібно повторно використати це значення, одним із варіантів може бути збереження його в деякій змінній, але тоді потрібно бути обережними щодо зіставлення таких змінних із відповідними групами, і код може стати досить заплутаним і нечитабельним. З іншого боку, в GAP є таке поняття як атрибут – структура даних, яка використовується для накопичення інформації, яку об’єкт “дізнається про себе протягом свого життя” (learns about itself during its lifetime). Розгляньмо наступний приклад:
GAP
G:=Group([ (1,2,3,4,5,6,7,8,9,10,11), (3,7,11,8)(4,10,5,6) ]);
gap> NrConjugacyClasses(G);time;NrConjugacyClasses(G);time;
ВИВІД
Group([ (1,2,3,4,5,6,7,8,9,10,11), (3,7,11,8)(4,10,5,6) ])
10
39
10
0
У цьому випадку група G має 10 класів спряженості, і
знадобилося 39 мілісекунд, щоб їх отримати під час першого виклику.
Другий виклик миттєво повертає результат, оскільки він був збережений в
G, саме тому, що NrConjugacyClasses є
атрибутом:
ВИВІД
<Attribute "NrConjugacyClasses">
Наша наступна задача — навчитися створювати власні атрибути.
Оскільки у нас вже є функція AvgOrdOfCollection, що
виконує необхідне обчислення, то найпростішим способом перетворити її на
атрибут є наступний:
GAP
AverageOrder := NewAttribute("AverageOrder", IsCollection);
InstallMethod( AverageOrder, "for a collection", [IsCollection], AvgOrdOfCollection);
У цьому прикладі спочатку ми оголосили атрибут
AverageOrder для об’єктів у категорії
IsCollection, а потім встановили функцію
AvgOrdOfCollection як метод для цього атрибута. Замість
функції AvgOrdOfCollection, тепер ми можемо викликати
AverageOrder.
Далі, ми можемо перевірити, що наступні виклики
AverageOrder з тим самим аргументом виконуються без
додаткових витрат часу. У цьому прикладі час виконання скорочується з 16
секунд до нуля:
ВИВІД
39020911/3628800
16445
39020911/3628800
0
Ви можете запитати, чому ми оголосили операцію для колекції, а не
лише для групи, і чому ми встановили неефективний метод
AvgOrdOfCollection. Зрештою, ми вже маємо набагато
ефективнішу функцію AvgOrdOfGroup.
Уявіть, що ми хочемо мати можливість обчислити середній порядок як для групи, так і для списку, який складається з об’єктів, що мають мультиплікативний порядок. Можна мати окрему функцію для кожного випадку, наприклад, як ми маємо зараз. Щоб зробити код більш універсальним, до нього можна додати перевірку типу обʼєкту, що розглядається, для виклику відповідної функції. Це може швидко стати складним, якщо у вас є кілька різних функцій для різних типів об’єктів. Натомість атрибути — це групи функцій, які називаються методами, а вибір методу в GAP знайде найефективніший метод на основі типів усіх аргументів.
Щоб проілюструвати це, зараз встановимо метод для атрибуту
AverageOrder для групи:
Якщо застосувати це до групи, для якої AverageOrder вже
обчислено, нічого не зміниться, оскільки GAP використовуватиме вже
збережене значення. Однак для новоствореної групи буде викликатися цей
новий метод:
ВИВІД
39020911/3628800
26
39020911/3628800
0
Як зрозуміти, який метод викликається
Спробуйте викликати
AverageOrderдля колекції, яка не є групою (список елементів групи та/або клас спряжених елементів групи).Побачити, який метод викликається, можна за допомогою функції
TraceMethods.Функція
ApplicableMethodв комбінації зPageSourceможе вказати на конкретні рядки у вихідному коді разом з коментарями.
Спеціальним видом атрибуту є властивість
(property), тобто атрибут із булевим значенням. Властивість
можна створити, використовуючи NewProperty:
Далі, встановимо метод для IsIntegerAverageOrder для
колекції. Зауважимо, що не обовʼязково спочатку створювати функцію, а
потім встановлювати її як метод. Замість цього, нову функцію можна
вказати як аргумент під час встановлення методу:
GAP
InstallMethod( IsIntegerAverageOrder,
"for a collection",
[IsCollection],
coll -> IsInt( AverageOrder( coll ) )
);
Зауважте, що AverageOrder є атрибутом, і саме це
забезпечить вибір оптимального методу.
Чи буває, що прийнятного методу взагалі не існує?
Так. У такому разі буде видано помилку “No-method-found”. Це
особливий вид помилки, який можна дослідити за допомогою таких
інструментів як ShowArguments, ShowDetails,
ShowMethods та ShowOtherMethods.
Наступні обчислення показують, що незважаючи на швидке обчислення середнього порядку для великих груп перестановок за допомогою класів спряжених елементів, для pc груп із бібліотеки Small Groups Library прямий перебір їх елементів працює швидше, ніж обчислення класів спряженості:
ВИВІД
56231
ВИВІД
9141
Без паніки!
Установіть метод для
IsPcGroup, який перебирає елементи групи замість знаходження її класів спряженості.Оцініть практичні межі можливостей цього методу. Чи можна знайти приклад pc групи, де перебір елементів повільніший, ніж обчислення класів спряженості?
- Позиційні об’єкти можуть накопичувати інформацію про себе “протягом життя”.
- Це означає, що наступного разу збережену інформацію можна буде отримати без жодних витрат часу.
- Методи — це групи функцій. Вибір методів визначить найефективніший метод на основі типів всіх аргументів.
- ‘Метод не знайдено’ — це особливий вид помилки з корисними інструментами налагодження, які допомагають її зрозуміти.