Чи можу я спростити нерівність "відстань (p1, p2) <відстань (p1, p3)?"


14

Я працюю над деякою векторною логікою, тому запитую: чи можна заощадити час процесора, спростивши цю нерівність:

distance(vector1, vector2) < distance(vector1, vector3)

Я бачу, що vector1це повторюється в обох випадках.


10
Просто коротке зауваження: ваш поточний метод дуже читабельний і його функцію можна відразу зрозуміти. Деякі з цих відповідей можуть виконати задане вами завдання, але набагато менш зрозумілі. Це добре, якщо продуктивність є сутнісною, але обов'язково коментуйте її належним чином, щоб врахувати втрату чіткості.
MikeS

3
Щоб продовжити коментар @ MikeS, продуктивність має бути сутнісною лише у таких випадках, якщо ви вже зробили аналіз або профілювання та визначили цей виклик як вузьке місце. Технічне обслуговування випереджає продуктивність, якщо ми говоримо про різницю між 305 кадрів в секунду і 303 кадрів в секунду.
Phoshi

Відповіді:


24

Так , ви можете спростити це. По-перше, перестаньте називати їх векторами. Вони є очками. Давайте назвемо їх A, Bі C.

Отже, ви хочете цього:

dist(A, B) < dist(A, C)

Замініть відстані на відстані у квадраті, а потім на крапкові вироби (із визначення довжини Евкліда . Замініть ACна AB + BC(тепер це справжні вектори). Розгорніть, спростіть, коефіцієнт:

dist(A, B < dist(A, C
dot(AB, AB) < dot(AC, AC)
dot(AB, AB) < dot(AB + BC, AB + BC)
dot(AB, AB) < dot(AB, AB) + dot(BC, BC) + 2 dot(AB, BC)
0 < dot(BC, BC) + 2 dot(AB, BC)
0 < dot(BC + 2 AB, BC)

Ось ти де:

dot(AB + AC, BC) > 0

З вашими векторними позначеннями:

dot(v2 - v1 + v3 - v1, v3 - v2) > 0

Це кілька доповнень і один крапковий продукт замість двох попередніх точкових продуктів.


Чи можете ви пояснити, як ви можете замінити a + b b = a a + c c версією крапкового продукту?
TravisG

2
@TravisG Я не впевнений у тому, про що ти питаєш. Якщо ваше питання, чому dist(A, B)²це те саме dot(AB, AB), це випливає з самого визначення евклідової довжини .
sam hocevar

2
Зрозуміло, це (дещо) спрощує рівняння математично, але не обов'язково "економить час процесора" для ОП. Це призводить до більшої складності та більшої кількості обчислень, ніж просто видалення квадратного кореня з початкових рівнянь відстані.
MichaelHouse

1
Виправте мене, якщо я помиляюся, але два точкових продукту - це 5 операцій на крапковий продукт плюс дві субстракції vec3, що в цілому 16 операцій, ваш спосіб має 3 суб3 субстанції плюс додавання, яке робить 12 операцій плюс крапковий продукт робить 17.
Луїс В

2
Цікаво, що результат - крапковий добуток двох протилежних діагоналей паралелограма. Але це не має значення. Я хотів сказати, що від цього повного спрощення не можна отримати величезну суму ; як вже згадували інші, це дозволяє приховувати чи ускладнювати те, що ви насправді намагаєтеся обчислити. Однак ви обов'язково хочете скористатися першим кроком. Уникати зайвого квадратного кореня завжди варто. Просто порівняння квадратів відстаней однакове, оскільки відстань є певною позитивною, навіть у складній площині.
TASagent

16

Так. Якщо ваша distanceфункція використовує квадратний корінь, ви можете спростити це, видаливши квадратний корінь.

Намагаючись знайти більшу (або меншу) відстань, x^2 > y^2 все-таки справедливо для x > y.

Однак подальші спроби математичного спрощення рівняння, ймовірно, безглузді. Відстань між vector1і vector2не є такою ж, як відстань між vector1і vector3. Хоча рівняння може бути спрощене математично, як показує відповідь Сема , форма, в якій він зараз знаходиться, швидше за все, така проста, як ви отримаєте з точки зору використання процесора.


У мене немає достатньої кількості представників, але я вважаю, що це принципово неправильно, я вважаю: "чи можу я заощадити час процесора, спростивши цю нерівність?" Відповідь - так.
я так заплутався

Відповідь - лише так, якщо в рівнянні відстані використовується квадратний корінь. Який я згадую.
MichaelHouse

Дійсна точка, я б відкликав своє твердження. Однак на 99% гарантовано, що користувач означає евклідову відстань sqrt (сума (різниці розмірів у квадраті))
я так заплутався

@imsoconfused Справедливо, я змінив порядок своєї відповіді, щоб спершу вказати найбільш вірогідний (99%) сценарій.
MichaelHouse

2
Так, мій досвід, коли ви маєте справу з подібними матеріалами, функція DistanceSquared дуже корисна. Це так само ясно і уникає дорогої операції sqrt.
Лорен Печтел

0

Деякі математики можуть допомогти.

Що ви намагаєтесь зробити:

<v1, v2> < <v1, v3> =>
sqrt((y2-y1)^2+(x2-x1)^2) < sqrt((y3-y1)^2+(x3-x1)^2) =>
y2^2 - 2*y2y1 + y1^2 + x2^2 - 2*x2x1 + x1^2 < y3^2 - 2*y3y1 + y1^2 + x3^2 - 2*x3x1 + x1^2

З чого можна видалити повторні змінні та згрупувати деякі інші. Операція, яку ви повинні перевірити:

y3^2 - y2^2 - 2*y1(y3-y2) + x3^2 - x2^2 - 2*x1(x3-x2) > 0

Сподіваюся, це допомагає.


-1

Справжнє питання, здається, як зменшити обчислення для визначення найближчого об'єкта?

Оптимізація цього часто робиться в іграх, хоча, з усіма оптимізаціями, вона повинна орієнтуватися на профіль і, часто, не спрощує речі.

Спосіб уникнення непотрібних обчислень на відстані для визначення найближчої речі - або всіх речей у певному діапазоні - це використання просторового індексу, наприклад, октре .

Це окупається лише за наявності великої кількості об’єктів. Всього за три об’єкти це навряд чи окупиться і, звичайно, не спрощує код.


4
Я думаю, що власне питання є досить простим, і ця відповідь не відповідає на це. Якщо ви хотіли роздумувати про глибші, нестаціонарні запитання ОП, які справді слід робити як коментар, якщо ви не збираєтесь насправді відповісти на поставлене питання.

Я заперечую це, тому що виклик можливої ​​передчасної оптимізації не є відповіддю на проблему, коли явна оптимізація не шкодить ні читабельності, ні ремонту коду, ні заохочує незрозумілі практики. Коли ви насправді можете написати простий та оптимізований код, чому б не зробити цього? Це, звичайно, не завадить зробити це, навіть якщо у вас план вищого рівня (жоден розробник ігор ніколи не відмовить кілька зайвих мікросекунд на кадр, особливо на консолях).
теодрон

@teodron: "Коли ви насправді можете написати простий і оптимізований код, чому б не зробити це?" - Через те, що ОП (а тепер і ми) зараз витратив незначну кількість часу на оптимізацію чогось, що може не дати йому жодної користі.
BlueRaja - Danny Pflughoeft

@ BlueRaja-DannyPflughoeft Я погоджуюся з цим, що це незначне значення (отже, незначна оптимізація, якщо вона використовується для декількох сотень викликів на кадр, але якщо коефіцієнт масштабу збільшується до тисяч, речі, безумовно, змінюються). Однак ми всі вільні, щоб не витрачати час на спроби відповісти / оптимізувати те, що ми вважаємо нежиттєздатним. В ОП просили одне, люди припускали, що ОП не знає стратегій вищого рівня та практики профілювання. Я особисто вважаю за краще робити такі зауваження в коментарях, а не у відповідях. Вибачте за те, що настільки багатослівний :(.
teodron

-3

це залежить від того, яким є вихід відстані (v1, v2)

якщо це десятковий (поплавковий або подвійний) над вектором, ймовірно, що відстань у квадраті буде набагато швидшою


5
Я не бачу, що це floatстосується нічого.
MichaelHouse

я мав на увазі поплавок над іншим вектором, просто не пояснений особливо добре (і я думаю, ви це знали)
RoughPlace

5
Я навмисно не розумів. Я досі не впевнений, що ти маєш на увазі. Я не знаю, чому функція відстані повертає вектор.
MichaelHouse
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.