Перейти к содержимому

Pengoid

Пользователи
  • Публикации

    18
  • Зарегистрирован

  • Посещение

  • Победитель дней

    1

Сообщения, опубликованные пользователем Pengoid


  1. 15 минут назад, Doob сказал:

    Встречный вопрос: зачем?

    Я вижу так: перебираются плотности блоков для каждого сканирования, пока для нашей итоговой формулы не выполнится условие с целым числом. Чтобы не подбирать несуществующие значения, создается массив плотностей существующих блоков. Или ты видишь другой вариант?


  2. Я ставил поочередно несколько иридиевых ящиков из ic2 с воронками, под последним ящиком ставился робот. Он поочередно вытаскивал блоки, устанавливал их перед собой, сканировал с помощью .analyze(), записывал твердость в файл, ломал блок ваджрой на шелк и клал в ящик справа от себя, под которым была воронка в другие ящики. Я просто накидал блоки из JEI, это не очень быстро, но зато точно все проверит. Вот откуда у меня столько твердостей было)

    Также в зависимости от ситуации программа может отсеивать твердости блоков, которые точно не попадутся.


  3. Только что, eu_tomat сказал:

    Полагаю, это описка. А ход рассуждений одинаков, вы оба нашли решение.

    Все не так гладко, только сейчас заметил, я ошибся два раза, но прийти к результату это не помешало.

    N - это шум, P0 - это данные сканирования, H - реальная твердость, которую я даже не указал, хотя в способе решения предлагал ее подставлять.

    13 часа назад, Pengoid сказал:

    K = (P0 - N)*128/(0.0606*R).

    По логике P0 = N + H.

    Но из своей формулы я получаю:

    13 часа назад, Pengoid сказал:

    N = P0 - R*0.0606*[rand(-128; 127)]/128

    N = P0 - N, хотя на самом деле H = P0 - N, чем процитированная формула и равняется, разница полученного значения и шума.

    Короче, я перепутал N с H.

    Тогда получается, что формулы идентичны.

     

    Мало-ли, вдруг кто-то потом заметит.


  4. 17 минут назад, Doob сказал:

    (R - H) / D / N * 128 * 33 % 1

    Можешь, пожалуйста, объяснить почему результат должен быть не равен нулю? А то я получил противоположный результат с такой же формулой, но без остатка от деления, то есть у меня число должно быть приблизительно целым, а значит по твой формуле у меня результат должен быть очень близким к нулю или нулем.


  5. Есть идея при условии, что мы пробуем отличать блоки, твердость которых кратна 0.1 (для кварцевых и других блоков со странной плотностью не работает).

    Из неправильно выведенной мною формулы:

    1 час назад, Pengoid сказал:

    N = R*0.0606*[рандом от -128 до 127]/128 - P0

    Которая на самом деле N = P0 - R*0.0606*[rand(-128; 127)]/128

    Будем перебирать возможные плотности блоков в диапазоне максимальной погрешности.

    На максимальном расстоянии будет больше 70 вариантов, но надо учесть, что плотность не может быть отрицательной (если это не бедрок), этот диапазон скорее всего можно будет сузить.

    Тогда из формулы рассчитываем число, выдаваемое генератором:

    K = (P0 - N)*128/(0.0606*R).

    Если полученное число целое или крайне близко к таковому, есть вероятность, что это нужный результат, надо будет проверить.

     

    Upd:

    Можно создать массив плотностей возможных блоков, а не подбирать с шагом в 0.1.

    • Нравится 1

  6. Ой, кажись, я понял принцип. У нас при сканировании получается 256 вариантов шума, а на выходе мы имеем точное число с плавающей точкой.

    Считаем расстояние R. Тогда шум N = R*0.0606*[рандом от -128 до 127]/128 - P0 (полученное значение после сканирования), и тогда каким-то образом рандом подгоняется к преполагаемому значению твердости сканированного блока. Что-то я тугодумлю.


  7. 1 минуту назад, eu_tomat сказал:

    А ты уже решил мою задачу, опираясь лишь на первый результат сканирования? Как её решить без извлечения корня, при этом не увеличив объём вычислений на порядок?

     

    Да, точно же! Получается, что теоретически какое угодно может быть значение плотности. Эти хвосты могут создать проблему для нового метода подавления шумов.

     

    А что у кварца за инструмент такой подходящий для ломания, что получилась такая странная плотность с хвостом?

    1. Насколько я пытался догадаться, вы хотите заранее вычислить рандом, который выдаст генератор, чтобы просто вычесть шум из значения сканированного блока для получения реальной плотности блока. В таком случае мои полномочия все.

     

    2. Так как я неправильно понял метод подавления шумов, написал не в тему.

     

    3. Мои предположения: в майнкрафте для каждого блока задается какое-то значение, это или и есть та самая твердость, или же значение, из которого при умножении на какую-то константу можно получить эту же твердость. По наблюдениям могу сказать, что для каждого инструмента должен быть некий коэффициент скорости добычи, который игнорируется, если инструмент не подходит и в качестве коэффициента используется скорость добычи руки (все это для выживания).

    Такая странная плотность у некоторых блоков для меня остается загадкой, но она не должна зависить от инструмента.


  8. 1 час назад, eu_tomat сказал:

    Я не планирую хранить хеши шумов. Может быть, подумаю о хранении расстояний, чтобы не вызывать многократно функцию извлечения квадратного корня. Но оставшаяся часть реверсивных вычислений, мне кажется, слишком проста для того, чтобы занимать память этими хешами. Но да, надо будет проверить эти предположения в реальной работе. Тогда заодно и дам свою оценку шанса коллизий.

    А точно нужно вычислять само расстояние? Если требуется сравнить расстояние с другим значением, можно просто само значение возвести в квадрат, вместо того, чтобы извлекать корень, это менее ресурсоемко.

     

    1 час назад, eu_tomat сказал:

    Кстати, о коллизиях. Плотности блоков чаще всего кратны единице. Но бывает и 1.5 как у камня. Чем определяется плотность того или иного блока? Насколько дробной может быть плотность, как это регламентируется? Может ли, плотность блока быть 1.618, например? Какие они вообще бывают стандартные, типичные плотности?

    Я просканировал кучу блоков, и думаю плотность зависит напрямую от времени ломания блока подходящим типом инструмента.

    Точнее, соотношение времени ломания для одного и того же подходящего для выбранных блоков инструмента будет равняться соотношению плотностей. В основном они кратны 0.1, есть исключения, например кварцевый блок, у него 0.80000001192093, но я во всех случаях пренебрегал подобными хвостами. У листвы плотность 0.2, песка, земли, плотного льда - 0.5, блока алмаза, железа - 5. У факелов, некоторых редстоун-компонентов плотность 0 (они мгновенно ломаются рукой в выживании). Исключение - обсидиан, имеет плотность 50, точно такая же у небесного камня из AE2 (можно легко находить метеориты). Есть два блока из IC2, которые имеют относительно уникальные плотности: 20 у базальта и 80 у укрепленного камня, я их хотел использовать для того, чтобы роботы могли точно определять свои координаты без улучшения навигации. У бедрока плотность -1, скорее всего так будет для всех неломающихся блоков.

    Для всех вышеперечисленных блоков соблюдалась закономерность с временем ломания. И да, "hardness" - это скорее твердость, чем плотность, что лучше объясняет прямую зависимость значения от времени разрушения блока и значение -1 для бедрока.

    • Нравится 1
    • Спасибо 1

  9. Еще после каждого сканирования можно считать суммы, которые изначально равны нулю.

    S1 = S1 + math.abs(P1 - P0) и S2 = S2 math.abs(P2 - P0), а потом сравнивать эти суммы.

    Если S1 < S2, то скорее всего плотность блока - P1, и наоборот.

     

    Надо бы найти зависимость шанса попадания от дистанции, разницы между плотностями данных блоков и количества сканирований.


  10. 3 часа назад, eu_tomat сказал:

    Произведено три сканирования одного и того же блока, находящегося на расстоянии 30 блоков от геосканера. Известно, что это либо руда с плотностью 3, либо камень с плотностью 1.5. Доски, булыжник, свинцовую руду пока не рассматриваем для упрощения задачи. Полученные значения (округлённо): {1.295, 3.341, 1.580}.

     

    Вопросы: что за блок мы просканировали: это руда или камень? Почему? Какое количество сканирований оказалось достаточным для однозначной идентификации блока?

    Вариант, чтобы определить со 100% точностью за пока-что неопределенное количество сканирований.
     

    Алгоритм

    Имеем две возможные плотности для блока P1 и P2, причем P1 < P2.

    Находим R и максимальный шум Nmax = R*0.0606

    Пусть, наш диапазон определяется переменными PMin, PMax = P2 - NMax, P1 + Nmax.

    Сканируем, блок пока полученное значение P0 не выйдет за диапазон [PMin; PMax].

    При выходе из диапазона: если P0 < PMin - блок имеет плотность P1, если P0 > PMin - блок имеет плотность P2.

     

    Примерная оценка шанса выпадения за установленный диапазон

    Минимально требуемую погрешность можно вычислить за формулой: Nmin = Nmax - math.abs(P1-P2), причем если Nmin < 0, блок определяется с первого сканирования. Чем больше соотношение NMax/NMin, тем меньше сканирований в среднем понадобится для определения блока.

     

    Применение на примере

    R уже дано, а N = 30*0.0606 = 1.8 (округленно). Находим диапазон значений для блоков с данными плотностями, имеем [1.2; 3.3]. Сканируем до тех пор, пока значение не выйдет за промежуток, и точно узнаем блок. Если это был блок с плотностью 1.5, то условие выполнится, когда погрешность будет <-0.3, а для 3 - >0.3, а это довольно таки немного, 0.3 в 6 раз меньше 1.8, по этому шанс попадания в этом случае довольно большой.

    Кстати, если не округлять 1.818 + 1,5 < 3.341 (из примера), а значит плотность равна 3.

    • Нравится 1

  11. 3 часа назад, Doob сказал:

    Берем минимальную и максимальную плотность для руды и камня, сравниваем их.

    YY3ps3W.png

    Видим, что на расстоянии в 12 блоков имеется пересечение плотностей, при максимально возможном уровне шума. Следовательно, до 12 блока можно легко обнаруживать и добывать руду.

    Нам нужен камень? Вряд-ли. Пока идем до руды, его и так не мало набирается, следовательно, надо исключить попадание возможных плотностей камня в список целей добычи.

     

    Путем нехитрых манипуляций, выводим формулу получения максимального шума из расстояния. N = R * 0.0606

    Для этого не придется делать тысячи сканов всех блоков, ведь в конфиге написано, что зависимость линейная, да и в коде можно глянуть.

     

    Чтобы отнять максимум плотности камня от минимума плотности руды, можно заюзать функцию math.max, в результате имеем возможность с вероятностью примерно в 99.99% не перепутать камень с рудой на любом расстоянии.

    Получаем уровень шума: N = math.sqrt(x^2 + y^2 + z^2) * 0.0606

    Вычисляем минимально возможную плотность для текущего расстояния: math.max(3 - N, 1.5 + N)

    Если полученное число меньше результата сканирования, то все норм, этот блок точно плотнее камня и за ним можно ехать.

    Разве это не то же самое, что я описал выше? Правда, в вашем примере все понятнее, также разница в другом порядке вычислений и в том, что я получил константу 0.0606 очень глупым, экспериментальным путем в виде 1/16.5, что почти не отличается от реальности, а все остальные вычисления такие же. Только еще я приводил способ получения оптимальной области сканирования в зависимости от диапазона высот генерации руды.

    Чуть подробнее опишу, как делал я и почему предпочитаю немного иной порядок действий.

    Сначала единоразово вычисляю: максимально допустимую погрешность для того, чтобы отличить блок с плотностью P1 от P2:

    N = math.abs(P1-P2)/2, максимальное R^2 = (N/0.0606)^2 для вычисления области сканирования, порог допустимых значений PMin, PMax = P1 - N, P1 + N. Если уже вычислена область, на которой происходит сканирование, остается только сравнивать полученную плотность P0 сканированного блока: PMin < P0 < PMax. Если условие выполняется, то результат аналогичный вашему и моему первому примерам.

     


  12.  Провел эксперимент, в котором нашел зависимость погрешности геосканера от расстояния между самим сканером и сканируемым блоком.

     

    Результаты

    Максимальная погрешность NMax строго пропорциональна расстоянию R, которую можно вычислить по формуле NMax = R/16.5 (более точный вариант: NMax = R*0.0606 - товарищи посмотрели в код и подсказали).
    При любом расположении сканируемого блока в зоне видимости сканера 65*65*64 (сканер находится в центре) расстояние можно вычислить по формуле: R = x^2 + y^2 + (z - 33)^2, где x и y - координаты сканируемого столба относительно сканера, а z - номер элемента в таблице, которую возвращает сканер.

     

    Применение

    Знание максимальной погрешности NMax для данного R позволяет нам рассчитать максимальное расстояние, на котором данным методом возможно первым же сканированием гарантированно отличить два блока с твердостями P1 и P2.
    Для этого требуется вычислить максимально допустимый шум N, при котором полученные со сканера значения точно не будут пересекаться. Получаем неравенство: P1 + N < P2 - N, имеем: N < (P2 - P1)/2.
    В итоге R = (P2 - P1)/(2*0.0606).

     

    Пример применения

    Допустим, мы хотим робота, добывающего нам алмазы.
    Для ускорения процесса средствами геосканера отличаем алмазную руду от камня, чтобы не тратить слишком много времени на его выкапывание.
    Дополнительное время могут занимать и лишние перемещения робота, а значит робот должен не путать руду с камнем и сканировать как можно большую площадь вокруг себя, следовательно подходящей фигурой для области сканирования будет цилиндр. Чтобы узнать его радиус и высоту, нужно узнать радиус описанной вокруг него сферы.

    shcedevr-min.png.aab7a5adb2c794c1fba520c2e2e5002b.png
    Воспользуемся описанным выше методом: R = (3 - 1,5)/(2*0.0606) = 12.376

    Алмазы генерируются до 16 высоты, а бедрок - до 5. Если руда не заспавнилась на 3 высоте, ниже копать скорее всего нечего. Отсюда высота цилиндра H = 16 - 3 = 13 блоков. Тогда максимальное расстояние до края цилиндра по вертикали h = (H - 1)/2. За теоремой Пифагора найдем радиус цилиндра r = (R^2 - h^2)^(1/2).

    Тогда за той же теоремой получаем, что r^2 = x^2 + y^2, где x и y - максимальные координаты сканирования относительно геосканера. Так мы узнаем, до каких x и y мы можем со 100% точностью отличить алмазную руду от камня.

     

    Сам эксперимент

    1. Создавался кубоид 65*65*64 из обсидиана, так как это максимальная зона сканирования для геосканера.

    2. Запихнул робота с геосканером в центр по горизонтали, на 33-ий блок по счету снизу по вертикали (можно было создать 33*33*33 и запихнуть робота в угол, но тогда надо будет определять, в какую сторону сканировать).

    3. Загрузил в него с помощью дискеты программу, имеющую функцию "scan", которая многогратно сканирует один и тот же блок в определенных координатах, возвращает среднюю, минимальную и максимальную погрешность.

    local component = require "component"
    local io = require "io"
    
    local geolyzer = component.geolyzer
    
    local path = "/home/geoScanData.txt"
    local accuracy = 10
    local hardness = geolyzer.analyze(3).hardness
    local radius = 32
    local average, min, max = {}, {}, {}
    
    local function compareData (scanData, sum, min, max)
      local lMin, lMax = min, max
      if scanData < min then
        lMin = scanData
      end
      if scanData > max then
        lMax = scanData
      end
      return sum + scanData, lMin, lMax
    end
    
    local function scan(x, y, zMin, zMax, hardness, accuracy)
      local sum, min, max = 0, 2, 0
      for i = 1, accuracy do
        local scanData = geolyzer.scan(x, y)
        for j = zMin, zMax do
          sum, min, max = compareData(math.abs(scanData[j]-hardness), sum, min, max)
        end
      end
      return sum/(accuracy*(zMax-zMin+1)), min, max
    end
    
    local function DGN(k, radius, x, y, z, hardness, accuracy)
      for i = 1, radius do
        average[i+k], min[i+k], max[i+k] = scan(i*x, i*y, 33-i*z, 33-i*z, hardness, accuracy)
        print(average[i+k].."\n"..min[i+k].."\n"..max[i+k].."\n"..i.."/"..radius.."/"..x+y+z.."\n")
      end
    end
    
    DGN(0, radius, 1, 0, 0, hardness, accuracy)
    DGN(radius, radius, 1, 1, 0, hardness, accuracy)
    DGN(radius*2, radius, 1, 1, 1, hardness, accuracy)
    
    print("Done!")
    
    file = io.open(path, "w")
    local len = #average
    for i = 1, len do file:write(average[i].."\n") end file:write("\n")
    for i = 1, len do file:write(min[i].."\n") end file:write("\n")
    for i = 1, len do file:write(max[i].."\n") end file:write("\n")
    io.close()

    Три вызова функции "DGN" вызывают функцию "scan" по порядку для каждого блока по определенной линии от робота до края кубоида.

    На изображении ниже робот находится в углу, а сканируемые блоки для первого, второго и третьего вызова окрашены в цвета, соответствующие окраскам номеров вызовов.

    Это сделано для того, чтобы проверить, можно ли вычислять расстояние до блока описанными выше формулами, влияет ли отклонение по нескольким осям на результат. В первом вызове проверяются блоки отдаленные только по одной оси, во втором - по двум, в третьем - по трем.

    2020-04-23_10_22_14.png.ae61a671292a118386347205fe40ddda.png

    Потом программа сохраняет все результаты в файл, после чего я ввожу данные в excel: GeolyzerNoise.xlsx.

    Первый график показывает зависимость максимальной погрешности от расстояния для 500 сканирований каждого блока. Таким образом расстояние до блока можно вычислять по указанной ранее формулой, результат не зависит от количества осей, по которым блок смещен относительно сканера.

    Shedule1-min.png.f0e83ca7a505c0eb9323dd6672ed4f50.png

    Отсюда я и получил константу 1/16.5

     

    Второй график показывает то же самое для средних значений. Еще на нем видно, что даже 30 сканирований дают очень низкую точность, по этому вычислять твердость средним арифметическом невыгодно по затратам времени и энергии.

    Shedule2-min.png.15aa402e9c049db9b2f2b0fd0f32e7fc.png

     

    Третий график показывает, что средняя арифметическая погрешность приблизительно в два раза меньше максимальной. Сам не знаю что с этим делать.

    Shedule3-min.png.84de6cd37d21a9d190ef72c9cdd96ead.png

    • Нравится 4
    • Одобряю 1

  13. 59 минут назад, eu_tomat сказал:

    Смотря какой смысл вкладывать в слово "сам".

     

    В общем случае робот не может вставлять и вынимать улучшения в собственных слотах улучшений без каких-либо вспомогательных приспособлений.

     

    Я для этой цели обычно использовал вспомогательного робота или схему на транспозере. Если требовалось лишь вставить что-либо в слот робота, то я даже использовал обычную воронку. Но робот может самостоятельно установить и использовать эти механизмы.

    Спасибо большое.


  14. Допустим, у робота установлены контейнеры для улучшений. Можно ли сделать так, чтобы робот сам мог вставлять и вытягивать улучшения, используя эти дополнительные слоты с помощью лишь своего инвентаря?

×
×
  • Создать...