Рандомизировать матрицу в Perl, сохраняя итоги строк и столбцов

Явное создание папки out, а затем установка выходного пути на C:\Users\USERNAME\IdeaProjects\PROJECTNAME\out

, казалось, работала для меня, когда только out, и ожидая, что IntelliJ сделает папку не такой.


Также попробуйте сделать IntelliJ новой конфигурацией запуска:

Найдите предыдущую, нажав

, затем удалите его

и нажмите ОК.

Теперь (ВАЖНЫЙ ШАГ) откройте класс, содержащий ваш основной метод. Это, вероятно, проще всего сделать, щелкнув имя класса в левой части панели проекта.

Дайте 'Alt + Shift + F10, и вы должны получить

Теперь нажмите Enter !!

Tadah ?? (Работало?)

11
задан Sinan Ünür 25 January 2010 в 16:05
поделиться

6 ответов

Проблема с вашим текущим алгоритмом Это то, что вы пытаетесь перетасовать свой выход из мертвых концов - в частности, когда ваш @LETTERS и @Numbers массивы (после начального перемены @numbers ) Укажите одну и ту же ячейку более одного раза. Этот подход работает, когда матрица мала, потому что она не займет слишком много попыток найти жизнеспособную повторную таблицу. Тем не менее, это убийца, когда списки большие. Даже если бы вы могли охотиться на альтернативы более эффективно - например, пробовать перестановки, а не случайные перетасовывающиеся - подход, вероятно, обречен.

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

Например, начнем с вашего примера матрицы (вызовите его M1). Случайно выберите одну клетку для изменения (скажем, A1). На данный момент матрица находится в незаконном состоянии. Наша цель будет исправлять его в минимальном количестве редактиций - специально еще 3 редактирования. Вы реализуете эти 3 дополнительных редактирования «ходьбами» вокруг матрицы, при этом каждый ремонт строки или столбца, полученной другой проблемой, пока вы не прогуливаетесь по полным кругу (Err ... Полный прямоугольник).

Например, после изменения A1 от 0 до 1 есть 3 способа прогулки для следующего ремонта: A3, B1 и C1. Давайте решим, что 1-я редактирование должно исправить строки. Итак, мы выбираем A3. На втором редактировании мы исправим столбец, поэтому у нас есть выбор: B3 или C3 (скажем, C3). Окончательный ремонт предлагает только один выбор (C1), потому что нам нужно вернуться в столбец нашего оригинального редактирования. Конечный результат - новая действительная матрица.

    Orig         Change A1     Change A3     Change C3     Change C1
    M1                                                     M2

    1 2 3        1 2 3         1 2 3         1 2 3         1 2 3
    -----        -----         -----         -----         -----
A | 0 0 1        1 0 1         1 0 0         1 0 0         1 0 0
B | 1 1 0        1 1 0         1 1 0         1 1 0         1 1 0
C | 1 0 0        1 0 0         1 0 0         1 0 1         0 0 1

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

Этот подход быстро генерирует новые действительные матрицы. Он не обязательно будет не обеспечить случайные результаты: M1 и M2 все равно будут очень коррелированы друг с другом, точка, которая станет более непосредственно очевидной, поскольку размер матрицы растет.

Как вы увеличиваете случайность? Вы упомянули, что большинство клеток (99% или более) являются нулями. Одна идея будет продолжаться так: для каждого 1 в матрице установите его значение 0, а затем отремонтируйте матрицу с помощью метода 4-редактирования, изложенные выше. По сути, вы будете перемещать все свои новые, случайные места.

Вот иллюстрация. Здесь, вероятно, существует дальнейшая оптимизация скорости, но этот подход дал 10 новых матрицей 600x600, на 0,5% плотность, за 30 секунд или около того на коробке Windows. Не знаю, достаточно ли это достаточно быстро.

use strict;
use warnings;

# Args: N rows, N columns, density, N iterations.
main(@ARGV);

sub main {
    my $n_iter = pop;
    my $matrix = init_matrix(@_);
    print_matrix($matrix);
    for my $n (1 .. $n_iter){
        warn $n, "\n"; # Show progress.
        edit_matrix($matrix);
        print_matrix($matrix);
    }
}

sub init_matrix {
    # Generate initial matrix, given N of rows, N of cols, and density.
    my ($rows, $cols, $density) = @_;
    my @matrix;
    for my $r (1 .. $rows){
        push @matrix, [ map { rand() < $density ? 1 : 0  } 1 .. $cols ];
    }
    return \@matrix;
}

sub print_matrix {
    # Dump out a matrix for checking.
    my $matrix = shift;
    print "\n";
    for my $row (@$matrix){
        my @vals = map { $_ ? 1 : ''} @$row;
        print join("\t", @vals), "\n";
    }
}

sub edit_matrix {
    # Takes a matrix and moves all of the non-empty cells somewhere else.
    my $matrix = shift;
    my $move_these = cells_to_move($matrix);
    for my $cell (@$move_these){
        my ($i, $j) = @$cell;
        # Move the cell, provided that the cell hasn't been moved
        # already and the subsequent edits don't lead to a dead end.
        $matrix->[$i][$j] = 0
            if $matrix->[$i][$j]
            and other_edits($matrix, $cell, 0, $j);
    }
}

sub cells_to_move {
    # Returns a list of non-empty cells.
    my $matrix = shift;
    my $i = -1;
    my @cells = ();
    for my $row (@$matrix){
        $i ++;
        for my $j (0 .. @$row - 1){
            push @cells, [$i, $j] if $matrix->[$i][$j];
        }
    }
    return \@cells;
}

sub other_edits {
    my ($matrix, $cell, $step, $last_j) = @_;

    # We have succeeded if we've already made 3 edits.
    $step ++;
    return 1 if $step > 3;

    # Determine the roster of next edits to fix the row or
    # column total upset by our prior edit.
    my ($i, $j) = @$cell;
    my @fixes;
    if ($step == 1){
        @fixes = 
            map  { [$i, $_] }
            grep { $_ != $j and not $matrix->[$i][$_] }
            0 .. @{$matrix->[0]} - 1
        ;
        shuffle(\@fixes);
    }
    elsif ($step == 2) {
        @fixes = 
            map  { [$_, $j] }
            grep { $_ != $i and $matrix->[$_][$j] }
            0 .. @$matrix - 1
        ;
        shuffle(\@fixes);
    }
    else {
        # On the last edit, the column of the fix must be
        # the same as the column of the initial edit.
        @fixes = ([$i, $last_j]) unless $matrix->[$i][$last_j];
    }

    for my $f (@fixes){
        # If all subsequent fixes succeed, we are golden: make
        # the current fix and return true.
        if ( other_edits($matrix, [@$f], $step, $last_j) ){
            $matrix->[$f->[0]][$f->[1]] = $step == 2 ? 0 : 1;
            return 1;
        }
    }

    # Failure if we get here.
    return;
}

sub shuffle {
    my $array = shift;
    my $i = scalar(@$array);
    my $j;
    for (@$array ){
        $i --;
        $j = int rand($i + 1);
        @$array[$i, $j] = @$array[$j, $i] unless $i == $j;
    }
}
9
ответ дан 3 December 2019 в 08:04
поделиться

Благодарите код Perl FMc. На основе этого решения я переписываю его в Python (для моего собственного использования, и совместно используйте здесь для большей ясности), как показано ниже:

matrix = numpy.array( 
    [[0, 0, 1], 
     [1, 1, 0], 
     [1, 0, 0]]
)

def shuffle(array):
    i = len(array)
    j = 0
    for _ in (array):
        i -= 1;
        j = random.randrange(0, i+1) #int rand($i + 1);
        #print('arrary:', array)
        #print(f'len(array)={len(array)}, (i, j)=({i}, {j})')
        if i != j: 
            tmp = array[i]
            array[i] = array[j]
            array[j] = tmp
    return array

def other_edits(matrix, cell, step, last_j):
    # We have succeeded if we've already made 3 edits.
    step += 1
    if step > 3: 
        return True

    # Determine the roster of next edits to fix the row or
    # column total upset by our prior edit.
    (i, j) = cell
    fixes = []
    if (step == 1):
        fixes = [[i, x] for x in range(len(matrix[0])) if x != j and not matrix[i][x] ]
        fixes = shuffle(fixes)
    elif (step == 2):
        fixes = [[x, j] for x in range(len(matrix)) if x != i and matrix[x][j]]
        fixes = shuffle(fixes)
    else:
        # On the last edit, the column of the fix must be
        # the same as the column of the initial edit.
        if not matrix[i][last_j]: fixes = [[i, last_j]]

    for f in (fixes):
        # If all subsequent fixes succeed, we are golden: make
        # the current fix and return true.
        if ( other_edits(matrix, f, step, last_j) ):
            matrix[f[0]][f[1]] = 0 if step == 2 else 1
            return True

    # Failure if we get here.
    return False # return False

def cells_to_move(matrix):
    # Returns a list of non-empty cells.
    i = -1
    cells = []
    for row in matrix:
        i += 1;
        for j in range(len(row)):
            if matrix[i][j]: cells.append([i, j])
    return cells

def edit_matrix(matrix):
    # Takes a matrix and moves all of the non-empty cells somewhere else.
    move_these = cells_to_move(matrix)
    for cell in move_these:
        (i, j) = cell
        # Move the cell, provided that the cell hasn't been moved
        # already and the subsequent edits don't lead to a dead end.
        if matrix[i][j] and other_edits(matrix, cell, 0, j):
            matrix[i][j] = 0
    return matrix

def Shuffle_Matrix(matrix, N, M, n_iter):
    for n in range(n_iter):
        print(f'iteration: {n+1}') # Show progress.
        matrix = edit_matrix(matrix)
        #print('matrix:\n', matrix)
    return matrix

print(matrix.shape[0], matrix.shape[1]) 

# Args: N rows, N columns, N iterations.
matrix2 = Shuffle_Matrix(matrix, matrix.shape[0], matrix.shape[1], 1) 

print("The resulting matrix:\n", matrix2)
0
ответ дан 3 December 2019 в 08:04
поделиться

Сейчас вы смешиваете 2 разных концепции: PinVoke и Com Interop.

PINVOOKE позволяет получить доступ к родным функциям C в пределах управляемого кода. Он работает путем определения маршалской совместимой подписи нативного метода в управляемом коде и маркировку его с атрибутом DLLLIMPORT . Это требует, и не может иметь, метаданную ссылку на родную DLL. DLL обнаружена во время выполнения, используя нормальные правила нагрузки для DLL Win32.

COM Interop позволяет получать доступ к COM совместимыми объектами из управляемого кода. Это делается путем получения маршала совместимого управляемого определения интерфейса COM, а затем набрать реферацию к объекту одним из нескольких способов. Получение управляемого определения часто выполняется посредством добавления ссылки на метаданные на PIA (основной сборке Interops) для компонента COM. До C # 4.0 эта ссылка не может быть удалена, без много работы и должна быть развернута с вашим приложением.

В этом конкретном примере вы используете COM Interop, а не PinVoke.

-121--4378841- [11304841-

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

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

Случайно раздающиеся столбцы не изменит ваши итоги для рядов и колонн, и случайным образом проводные ряды не будут. Итак, что я бы сделал, это первое переключение строк, а затем перемешивает колонны.

Это должно быть довольно быстро.

1
ответ дан 3 December 2019 в 08:04
поделиться
[1117851-

Не уверен, что он поможет, но вы можете попробовать идти от одного угла и для каждого столбца и строки вы должны отслеживать общую и фактическую сумму. Вместо того, чтобы пытаться ударить хорошую матрицу, попробуйте увидеть сумму как сумму и разделить его. Для каждого элемента найдите меньшее количество строк Total - фактическую строку и общее количество столбцов - фактическое значение столбцов. Теперь у вас есть верхняя граница для вашего случайного числа. Это понятно? Извините, я не знаю Perl, поэтому я не могу показать какой-либо код.

0
ответ дан 3 December 2019 в 08:04
поделиться

Как и @Gabriel, я не программист на Perl, так что, возможно, это то, что ваш код уже делает ...

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

Конечно, это может не соответствовать тем аспектам ваших требований, которые не являются явными.

0
ответ дан 3 December 2019 в 08:04
поделиться

Там нет необходимости назвать это. .NET имеет класс класса Uribuilder , который может помочь вам в создании вашего URL-адреса. Проверьте эту статью, чтобы увидеть, как она работает и сделать его немного более интуитивно понятным:

http://codeiDol.com/csharp/csharpckbk2/web/using-the-uribuilder-Class/

-121 1728974-

Шаг 1: Во-первых, я бы инициализирую матрицу для нулей и рассчитал необходимую строку и соток столбцов.

Шаг 2: Теперь выберите случайную строку, взвешенную по количеству 1S, которые должны быть в этой строке (так что ряд с подсчетом 300 с большей вероятностью будет выбран, чем ряд с весом 5).

Шаг 3: Для этой строки выберите случайную колонну, взвешенную по количеству 1s в этой колонне (кроме игнорирования любых клеток, которые могут уже содержать 1 - больше на это).

Шаг 4: Поместите один в этой ячейке и уменьшите количество ряд, так и подсчета столбцов для соответствующей строки и столбца.

Шаг 5: Вернитесь к шагу 2, пока строки не будут не нулевым количеством.

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

a) Рекурсивно построить вышеуказанный алгоритм и разрешить отступление отказа.

b) Разрешить ячейку содержать значение, превышающее 1, если нет другого варианта и продолжайте идти. Затем в конце у вас есть правильный подряд ряд и столбец, но некоторые ячейки могут содержать цифры, превышающие 1. Вы можете это исправить, найдя группу, которая выглядит так:

2 . . . . 0
. . . . . .
. . . . . .
0 . . . . 1

и изменение его к:

1 . . . . 1
. . . . . .
. . . . . .
1 . . . . 0

Это должно быть легко Чтобы найти такую ​​группу, если у вас много нулей. Я думаю, что B), вероятно, будет быстрее.

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

5
ответ дан 3 December 2019 в 08:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: