Главная страница Случайная страница Разделы сайта АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
💸 Как сделать бизнес проще, а карман толще?
Тот, кто работает в сфере услуг, знает — без ведения записи клиентов никуда. Мало того, что нужно видеть свое раписание, но и напоминать клиентам о визитах тоже.
Проблема в том, что средняя цена по рынку за такой сервис — 800 руб/мес или почти 15 000 руб за год. И это минимальный функционал.
Нашли самый бюджетный и оптимальный вариант: сервис VisitTime.⚡️ Для новых пользователей первый месяц бесплатно. А далее 290 руб/мес, это в 3 раза дешевле аналогов. За эту цену доступен весь функционал: напоминание о визитах, чаевые, предоплаты, общение с клиентами, переносы записей и так далее. ✅ Уйма гибких настроек, которые помогут вам зарабатывать больше и забыть про чувство «что-то мне нужно было сделать». Сомневаетесь? нажмите на текст, запустите чат-бота и убедитесь во всем сами! Використання графічної бібліотеки opengl 6 страница
is_a(room2, room, always) is_a(room3, room, always) is_a(door12, door, always) is_a(door23, door, always) is_a(box1, object, always) is_a(box2, object, always) is_a(box3, object, always) connects(door12, room1, room2, always) connects(door23, room2, room3, always) stands(door12, opened, now) stands(door23, opened, now) is_in(box1, room1, now) is_in(box2, room2, now) is_in(box3, room3, now) is_in(robot, room2, now) is_at(robot, door12, now)
Неважко зрозуміти зміст бази даних. Вона формується відношеннями: is_a – приналежність об’єкта класу, connects – поєднання двох об’єктів третім (двох кімнат дверима), stands – стан об’єкта (дверей), is_in – місцезнаходження об’єкта (скриньки або робота у кімнаті), is_at – взаємне розташування одного об’єкта біля іншого. Слід зауважити, що такий опис має виключати протиріччя, для чого необхідно забезпечити спеціальну процедуру. Операторні схеми системи планування фактично представляють описи дій, що можуть виконуватися в межах описаної моделі світу. Для мобільного робота це можуть бути дії: відкрити (закрити) двері, перейти у кімнату N, перейти до об’єкта M, пересунути об’єкт P до об’єкта Q тощо. Кожна операторна схема практично містить у собі: 1) твердження результату реалізації операторної схеми – події, яку забезпечує операторна схема; 2) тест виконання – перевірка відсутності реалізованого цільового факту; 3) тест валідності – перевірка придатності операторної схеми для забезпечення цілі системи планування; 4) список передумов: постановка (і виконання) умов, що передують виконанню дії операторної схеми; 5) список вилучення – список подій, що застаріють на момент виконання операторної схеми; 6) список додавання – список подій, що вносяться операторною схемою. Схематично опис операторної схеми дії Перейти_до_Object зображено на рисунку 13.3.
Рисунок 13.3 – Структура опису дії у системі планування мобільного робота
Мету системи формулюють у вигляді бажаного факту, до якого система має перейти, наприклад: plan (is_at (box1, box2, now)), де plan – предикат, що забезпечує досягнення поставленої цілі – знаходження поруч об’єктів box1 та box2. Окрім вказаних компонентів проблемної області, у системі планування необхідно реалізувати, власне, вирішувач. Вирішувачем може бути предикат або набір предикатів у випадку реалізації мовою Пролог [13, 15] або набір відповідних функцій у випадку реалізації на C++ (автором реалізовані обидві схеми). Як вже зазначувалося, завдання у системі формулюється як бажаний факт стану системи. Якщо такий факт не знаходиться у базі даних (тест виконання), викликається вирішувач, що реалізує схему пошуку рішення. Пошук рішення передбачає: 1) пошук предикатної схеми, яка відповідає поставленому завданню (у тому числі перевірка валідності); 2) виконання списку передумов; 3) виконання списку викреслення; 4) виконання списку додавання. Слід враховувати, що при виконанні списку передумов (звичайно, якщо такий визначено) досягнення підцілей проводиться рекурсивним викликом вирішувача, що вимагає чітких умов виходу з рекурсії. Серед перспектив розвитку систем планування інтелектуальних роботів слід віднести, по-перше, розширення проблемної області. Таке розширення веде до зростання операторних схем та їх ускладнення. У випадках, коли одна мета може бути досягнута декількома шляхами, виникає необхідність попередньої оцінки складності операторної схеми. При цьому кожній схемі з набору, що забезпечує однакові цілі, відповідатиме відповідний коефіцієнт, а сам набір буде нечіткою множиною [12]. По-друге, функціонування роботів у реальному часі вимагатиме поліпшення процедур знаходження адекватних операторних схем, у тому числі із урахуванням алгоритмів „відкату”, відновлення попереднього стану предметної області. По-третє, розширення проблемної області визначатиметься розширенням кола операцій, виконуваних роботом, а послідовність виконання операцій (технологічний процес) визначатиме стратегію дій робота.
13.4 Реалізація програми системи планування робота у Visual C++
13.4.1 Розробка системи прийняття рішень Реалізація системи планування робота засобами Visual C++ має певні особливості. По-перше, підхід Пролог-програм, що ґрунтується виключно на базах даних, у Visual С++ утруднюється відсутністю безпосередньо вбудованих у мову С++ засобів обробки баз даних, що вимагатиме реалізації спеціальних засобів подання. По-друге, розробку Visual С++-програми буде неможливо уявити без реалізації системи виконання розроблених планів. Звісно, що вирішення завдання із розробки планів істотно залежатиме від початкового стану системи. Кожен об’єкт світу робота має бути однозначно описаним у БД програми. Початкова база даних програми відповідає схемі, поданій на рисунку 13.4.
Рисунок 13.4 – Початкове розташування об’єктів у системі планування Таким чином світ робота складатиметься з п’ятьох кімнат, поєднаних дверима (відкритими або закритими). У кімнатах знаходяться скриньки. Робот, як дієвий об’єкт такого обмеженого світу може виконувати такі дії: − переміщуватися до дверей або скриньки; − переміщуватися у певну кімнату; − відкривати або закривати двері; − завантажуватися скринькою та звільнятися від неї. Опишемо основні моменти розробки програми для системи розробки планів робота в обмеженому просторі, повний код якої наведено у додатку А. 1. Для опису початкового, поточного та кінцевого станів системи планування оголосимо клас СRoboPlan, наведений у прикладі 13.1.
Приклад 13.1 – Основний клас системи розробки планів робота class CRobotPlan {public: char *relname, *agent, *sobj1, *sobj2; CRobotPlan *next; CRobotPlan(); CRobotPlan(char *, char *, char *, char *, CRobotPlan *); CRobotPlan(char *, char *, char *, CRobotPlan *); void print(); CRobotPlan *dataformer(); CRobotPlan *addfact(char *, char *, char *, char *); CRobotPlan *delfact(char *, char *, char *, char *); CRobotPlan *delfact(char *, char *, int, char *); CRobotPlan * delfactall(char *rel, char *n); int dbtest(char*, char*, char*); int dbtest(char*, char*, char*, char*); int dbtest(char*, int, char*, char*); int dbtest(char*, int, char*, int); CRobotPlan *findfact(char *, char *); CRobotPlan *findfact(char *, char *, char *); CRobotPlan *findfact(char *, char *, char *, char *); CRobotPlan *findfact(char *, int, char *, char *); CRobotPlan *findfact(char *, int, char *, int); CRobotPlan *findfact(char *, char *, char *, int); CRobotPlan* Revers(CRobotPlan *);
void deciser(); char *find_action(); void support_action(char*); void old_cleaner(char*); void new_adder(char*); };
Як видно клас складається з трьох змінних-членів (типу покажчика на рядок) та ряду функцій. Поля *relname, *agent, *sobj1 та *sobj2 означають: ім’я відношення, що входить до складу факту бази даних; програмний суб’єкт (aгент), який виконує дію; два об’єкти sobj1 та sobj2, на які спрямовується дія. Наявність у класі покажчика *next вказує на організацію даних у вигляді зв’язаного списку [8]. Об’єкти класустворюватимуться конструкторами трьох типів, що відповідатимуть різним ситуаціям конструювання об’єктів. Функція dataformer() відповідає за ініціювання бази даних системи прийняття рішень, addfact() – за додавання фактів у базу даних від час роботи програми, а delfact() – у декілька реалізацій здійснює вилучення окремих фактів з БД програми. Функція delfactall() здійснює вилучення усіх фактів із подібними ознаками. Пере-вірка наявності або відсутності фактів у БД програми здійснюється за допомогою перевантаженої функції dbtest(), а пошук необхідних фактів – за допомогою findfact(). Також функції класу забезпечують друк бази даних (функція Print()) і обертання зв’язаного списку БД (функція Revers()). Функції deciser(), find_action(), support_action(), old_cleaner() та new_adder() безпосередньо реалізують прийняті схеми побудови систем планування. 2. У програмі автоматичної генерації планів робота факти про стан об’єктів системи подаються зв’язаним списком [7, 8] та ініціалізуються функцією dataformer():
Приклад 13.2 – Функція ініціалізації стану світу робота CRobotPlan *CRobotPlan:: dataformer() {CRobotPlan *a1=new CRobotPlan(" is_a", " room1", " room", NULL, NULL); CRobotPlan *a2=new CRobotPlan(" is_a", " room2", " room", NULL, a1); CRobotPlan *a3=new CRobotPlan(" is_a", " room3", " room", NULL, a2); CRobotPlan *a4=new CRobotPlan(" is_a", " room4", " room", NULL, a3); CRobotPlan *a5=new CRobotPlan(" is_a", " room5", " room", NULL, a4); CRobotPlan *a6=new CRobotPlan(" is_a", " door12", " door", NULL, a5); CRobotPlan *a7=new CRobotPlan(" is_a", " door23", " door", NULL, a6); CRobotPlan *a8=new CRobotPlan(" is_a", " door24", " door", NULL, a7); CRobotPlan *a9=new CRobotPlan(" is_a", " door34", " door", NULL, a8); CRobotPlan *a10=new CRobotPlan(" is_a", " door45", " door", NULL, a9); CRobotPlan *a11=new CRobotPlan(" is_a", " box1", " box", NULL, a10); CRobotPlan *a12=new CRobotPlan(" is_a", " box2", " box", NULL, a11); CRobotPlan *a13=new CRobotPlan(" is_a", " box3", " box", NULL, a12); CRobotPlan *a14=new CRobotPlan(" is_in", " robot", " room5", NULL, a13); CRobotPlan *a15=new CRobotPlan(" is_in", " box1", " room1", NULL, a14); CRobotPlan *a16=new CRobotPlan(" is_in", " box2", " room2", NULL, a15); CRobotPlan *a17=new CRobotPlan(" is_in", " box3", " room5", NULL, a16); CRobotPlan *a18=new CRobotPlan(" stands", " door12", " opened", NULL, a17); CRobotPlan *a19=new CRobotPlan(" stands", " door23", " closed", NULL, a18); CRobotPlan *a20=new CRobotPlan(" stands", " door24", " closed", NULL, a19); CRobotPlan *a21=new CRobotPlan(" stands", " door34", " closed", NULL, a20); CRobotPlan *a22=new CRobotPlan(" stands", " door45", " closed", NULL, a21); CRobotPlan *a23=new CRobotPlan(" connects", " door12", " room1", " room2", a22); CRobotPlan *a24=new CRobotPlan(" connects", " door12", " room2", " room1", a23); CRobotPlan *a25=new CRobotPlan(" connects", " door23", " room2", " room3", a24); CRobotPlan *a26=new CRobotPlan(" connects", " door23", " room3", " room2", a25); CRobotPlan *a27=new CRobotPlan(" connects", " door24", " room2", " room4", a26); CRobotPlan *a28=new CRobotPlan(" connects", " door24", " room4", " room2", a27); CRobotPlan *a29=new CRobotPlan(" connects", " door34", " room3", " room4", a28); CRobotPlan *a30=new CRobotPlan(" connects", " door34", " room4", " room3", a29); CRobotPlan *a31=new CRobotPlan(" connects", " door45", " room4", " room5", a30); CRobotPlan *a32=new CRobotPlan(" connects", " door45", " room5", " room4", a31); CRobotPlan *a33=new CRobotPlan(" is_at", " robot", " door45", NULL, a32); CRobotPlan *a34=new CRobotPlan(" is_a", " robot", " robot", NULL, a33); CRobotPlan *a35=new CRobotPlan(" is_with", " robot", " empty", NULL, a34); return a35; } 3. Для вирішення завдань системи реалізуємо функцію-вирішувач – deciser(), що структуруватиме послідовність прийняття рішень:
void CRobotPlan:: deciser() {if(! evil-> dbtest(relname, agent, sobj1, sobj2)) {char *action=find_action(); if (action){ support_action(action); old_cleaner(action); new_adder(action); }}} Вирішувач розпочинається з перевірки наявності у базі даних цільового факту. Насправді, якщо цільовий факт є вже присутнім у БД програми, будь-яка активність із програми втрачає сенс. Далі за допомогою функції find_action() знаходиться спосіб дій робота, що задовольняє поставленій меті завдання. Якщо необхідний спосіб дій знайдено, необхідно виконати усі передумови виконання дії – реалізується функцією support_action(). Функція old_cleaner() реалізує вилучення застарілих фактів з БД програми (список викреслення), а new_adder() додавання нових фактів (список додавання). Якщо, наприклад, перед системою виникає завдання, у програмі створюється об’єкт типу CRobotPlan, для якого викликається функція-вирішувач, наприклад:
goal=new CRobotPlan(“is_in”, ”robot”, ”room1”, NULL); // tested goal-> deciser();
у даному випадку задається цільовий факт знаходження робота у кімнаті “room1”. 4. Для знаходження способу дій робота, що відповідатиме меті програми, реалізуємо функцію find_action(). Вибір способу дій цілком залежить від вигляду цільового факту. Наприклад, якщо завдання програми – “відкрити двері 23” сформулювати як новий цільовий факт:
goal=new CRobotPlan(“stands”, ”door23”, ”closed”, NULL); //
у функції find_action() йому відповідатиме така ділянка програмного коду:
char *CRobotPlan:: find_action() {…………………………………… if(evil-> dbtest(" is_a", agent, " door") & & evil-> dbtest(" stands", agent, " opened")) return " close_door"; ……………………. } З програмного коду видно, що здійснюється перевірка, чи наявний факт “Двері23” у БД, і чи не знаходяться вони у відкритому стані. 5. Підтримка здійснення дій робота у програмі розробки планів реалізується функцією support_action(). Для кожного обраного способу дій у support_action() існує власний набір передумов. Зокрема дія “взяти скриньку” передбачатиме знаходження робота поряд з означеним об’єктом. Це реалізується такою ділянкою коду:
void CRobotPlan:: support_action(char *action) {if(! (strcmp(action, " take_box"))) {CRobotPlan *subgoal=new CRobotPlan(" is_at", " robot", sobj1, NULL); // підціль subgoal-> deciser(); } // вирішення підцілі …………. }
6. Реалізація списків викреслення та додавання забезпечується функціями old_cleaner() та new_adder(), що у випадку виконання дії “закрити двері” матимуть такі ділянки коду: void CRobotPlan:: old_cleaner(char *action) {………………………………… if(! (strcmp(action, " open_door"))) {evil=evil-> delfact(" stands", agent, " closed", NULL); } ………………………………….. } void CRobotPlan:: new_adder(char *action) {……………………………… if(! (strcmp(action, " open_door"))) evil=evil-> addfact(" stands", agent, " opened", NULL); ……………………………… }
З наведеного коду видно, що як результат виконання дії “закрити двері” вилучатиметься закритий стан дверей і додається відкритий. 7. Встановлення початкової мети системи планування легко реалізувати за допомогою спеціального діалогового вікна із комбінованими списками. Кінцевий вигляд такого діалогового вікна наведено на рисунку 13.5.
Рисунок 13.5 – Вигляд діалогового вікна формування мети робота
За допомогою комбінованих списків “Агент” (містить значення “робот”, “скринька1”, “скринька2”, “скринька3”), “Дія” (“перейти_до”, ”штовхати_до”, “відкрити”, “закрити”) та “Об’єкт дії” (усі двері, кімнати та скриньки) можна сформувати завдання робота. Натискання кнопки “Підтвердити” означатиме закінчення вибору, перевірку коректності завдання та запуск системи планування. Перелік дій, що, в результаті, запланує система прийняття рішень виводитиметься до списку у правій частині діалогового вікна. Натискання кнопки “Показати” запускає функції графічного відображення розробленого плану дій робота.
13.4.2 Реалізація графічного подання стану системи Створення системи планування дій робота потребує демонстрації дій, щодо яких прийнято рішення, у головному вікні програми. Тому другим аспектом програми є створення системи функцій графічного відображення. На рисунку 13.6 наведено повний вигляд інтерфейсу програми планування дій робота у замкненому просторі.
Рисунок 13.6 – Вигляд вікна програми планування дій робота
Під час побудови графічної компоненти системи планування слід звернути увагу на такі її аспекти: 1) у конструкторі головного вікна необхідно реалізувати об’єкти-складові віртуального вікна програми; 2) для дискретного переміщення графічних об’єктів необхідно реалізувати обробник таймера; 3) за допомогою окремих функцій реалізувати формування робочого протору робота та опис поточного стану об’єктів системи – робота, дверей, скриньок. Повний текст програми наведено у Додатку А.
13.5 Контрольні завдання
1. Пояснити загальні принципи проектування системи планування дій робота у обмеженому робочому просторі. 2. Пояснити структуру опису дії у системі планування дій робота. 3. Пояснити порядок знаходження рішень у програмі планування дій робота. 4. Пояснити порядок формування графічного інтерфейсу програми планування дій робота у обмеженому просторі.
|