Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Построение распределенной системы на J2EE


Автор: zone51 27.4.2006, 21:06
Всем доброго времени суток! В общем у меня стоит задача реализовать игру "судоку" на J2EE причем построить на основе этой технологии распределенное приложение, которое считало бы решение игры на нескольких машинах. Домашний сайт программы: sudoku.name
Описание игры здесь:
http://www.sudoku.name/rules/ru
Помогите пожалуйста разобраться в 2-вещах: выборе технологии распределения:
1)RMI
2)JINI
3)JavaSpaces
4)JMX
5)Jiro
6)CORBA
7)JXTA
Я более менее знаком с этими технологиями, мне кажется что лучше JINI или JavaSpaces. Но хотел бы услышать другие мнения. И если не трудно обьясните пожалуйста логическую вещь:распределенное приложение в моем случае это одно приложение, но работающее на нескольких машинах как на одной или это дробление задачи на подзадачи и распределение этих задач, то есть назначение, маштнам. Буду искренне благодарен за любую помощь.Заранее спасибо всем откликнувшимся. smile   

Автор: jimur 28.4.2006, 05:47
Цитата(zone51 @  27.4.2006,  21:06 Найти цитируемый пост)
это дробление задачи на подзадачи и распределение этих задач, то есть назначение, маштнам

в твоем случае скорее так
примерно представляю как реализовать с использовнаием RMI

А ты алгоритм решения не хочешь описать? Может там и распределеять нечего?

И какую задачу ты зочешь решать - генерацию новых начальныйх условий или решение существующих схем?

Для начала проще забить известные задачи-результаты smile

А J2EE тут зачем? 

Автор: zone51 28.4.2006, 11:55
Цитата

А ты алгоритм решения не хочешь описать? Может там и распределеять нечего?


Точно со слов препода известно что задача хорошо распарралеливается.
Над алгоритмом работаю.

Цитата

И какую задачу ты зочешь решать - генерацию новых начальныйх условий или решение существующих схем?


Начальная схема в виде апплета будет задаваться пользователем, как тут:
http://www.sudoku.name/sudoku-solver/ru

Цитата

Для начала проще забить известные задачи-результаты

Немного не понял..что значит известные? каждый раз игрок может от балды ввести начальное расположение

Цитата

А J2EE тут зачем? 

Ну вообще-то RMI,Jini и иже с ними это и есть J2EE или я ошибаюсь?

Спасибо.

  

Автор: wadissimo 28.4.2006, 12:23
тебе надо именно на j2ee написать? 
удобнее всего будет сделать кластер.
а jini , javaSpaces, jmx это не j2eе, но зато хорошие технологии для написания распределенных приложений, по-моему тебе следует обратить внимание на javaspaces. 

Автор: onsh76 28.4.2006, 12:44
wadissimo
>>по-моему тебе следует обратить внимание на javaspaces.  
Я интересовался ранее и спрашивал форумчан про JINI и JavaSpaces. Имели ли Вы опыт работы с ними?
Непонятен статус этой/их технологий: живы ли они вообще? Посоветуйте, плиз. 

Автор: ALKS 28.4.2006, 18:16
технологии то живы а вот распостранены слабо... мало с их использованием пишут (не заню почему, может потому что прорекламировали слабо smile ) как следствие найти людей которые реально сталкиались практически не возможно 

Автор: zone51 28.4.2006, 19:13
2ALL
Так какой вы все мене дадите совет? Ориентироваться на RMI?
Спасибо. 

Автор: ALKS 28.4.2006, 21:16
А RMI входит в J2SE, а не в J2EE так что вам низзя smile 

Автор: zone51 28.4.2006, 21:58
Цитата

А RMI входит в J2SE, а не в J2EE так что вам низзя 

Да нет, это не жесткое условие, просто мой прошлый курсач был по ж2ее так я и хотел связать, главное чтоб Java2. Что скажете насчет RMI? Стоит ли?

 

Автор: powerOn 28.4.2006, 22:36
А ты вообще как себе это все представляешь? 
Ты средство под задачу подстраивать будешь или задачу под средство??? 
Сначало было бы не плохо определиться что и как работать должно, а потом уж думать о реализации... 

Автор: onsh76 29.4.2006, 00:26
Цитата(zone51 @ 28.4.2006,  19:13)
2ALL
Так какой вы все мене дадите совет? Ориентироваться на RMI?
Спасибо.

На мой взгляд все зависит от требований к приложению. 
Я был в аналогичной ситуации, где от нас требовалась horizontal scalability, т.е. масштабируемость количеством единиц умеющих производить некую бизнесс логику, a не мощностью какого-то сервака. Плюс ко всему исполнение бизнесс логики требовало separate JVM с хорошим количеством heap-а, т.к. 3-rd party component просто требовал этого.

RMI-based решение было одним из неск-х опций... 

После рассмотрения "за/против" повариантно, мы решили рискнуть и поставили на Hessian-based веб сервис, где обьекты передаютса в сериализованном виде over http. Ориентировались на то, что по скорости это http://kgionline.com/articles/protocol_compare/doc/index.jsp. Web services кластеризуются(load balancing/failover) легче/дешевле решений основанных скажем на той же самой CORBA или RMI.   

Автор: jimur 29.4.2006, 06:50
Цитата(onsh76 @  29.4.2006,  00:26 Найти цитируемый пост)
После рассмотрения "за/против" повариантно, мы решили рискнуть и поставили на Hessian-based веб сервис, где обьекты передаютса в сериализованном виде over http. Ориентировались на то, что по скорости это будет близко к RMI. Web services кластеризуются(load balancing/failover) легче/дешевле решений основанных скажем на той же самой CORBA или RMI.   

У веб-сервисов в контексте этой задачи есть большой недостаток - с сервера нельзя изменять реализации вычислителей на клиентах.
RMI позволяет это делать:
- создаем интерфейс вычислителя, наследуем его от Serializable, включаем его в клиентскую джарку
- клиент регистрируется на сервере, при распределении вычислений клиентам даются нужные вычислители
Чтобы самому сильно не заморачиваться c RMI - воспользуйся http://www.springframework.org/docs/reference/remoting.html
 

Автор: zone51 1.5.2006, 19:27
Так, товарищи, спасибо вам за все ответы, но давайте подведем промеуточный результат.
Моя цель написать курсач без доказательства сверэффективности, оптимальности и т п.
Задача состоит в том чтобы реализовать древнюю японскую игру "Судоку". Она состоит в следующем:
Имеется поле 9х9 клеток, в этом поле 9 регионов 3х3, в правильном порядке, ну то есть разбито на блоки 3 на 3 клетки. В каждую клетку ставится цифра, имеется некоторое начальное расположение цифр. Задача заполнить все остальные клетки(не блоки) так, чтобы в каждой клетке была цифра, причем такой цифры больше не было бы в строке, содержащей эту клетку, столбце с этой клеткой и блоке, содержащем эту клетку.

Цитата с сайта http://www.sudoku.name/rules/ru

Цитата


Законы игры судоку 
В судоку играют на квадратном поле 9 на 9 клеток. Само поле поделено на районы (квадраты 3 на 3)
user posted image
В начале игры известны некоторое число цифр в определенных клетках
user posted image
Цель судоку заполнить все пустые клетки с помощью цифр 1-9 (по одной цифре на клетку), по следующим правилам: 

1. Цифра может появиться только один раз в каждой строчке

Можно user posted image
Нельзя user posted image

2. Цифра может появиться только один раз в каждом столбике

Можно user posted image
Нельзя user posted image

3. Цифра может появиться только один раз в каждом районе

Можно user posted image
Нельзя user posted image

Проще говоря, одна и та же цифра может появиться только один раз в каждой строчке, столбике и районе

MoonCat
Цитата

А ты вообще как себе это все представляешь? 


Обьясняю. По идее, если решать без распределенного принципа, это делается приблизительно так:

Цитата

class sudoku{
 private int pole[8][8];
 public int newN(int i,int j);//Вычисление нового элемента поля с индексом i,j
 public boolean isStr(int i,int num);//Проверка есть ли в строке
 public boolean isCol(int j,int num);//Проверка есть ли в столбце
 public boolean isReg(int i,int j,int num);//Проверка есть ли в регионе


Реализация функции newN:
Цитата

int newN(int i,int j){
 //Перебор цифр 
 for(int k=0;k<=9;k++)if(isStr(i,k) && isCol(j,k) && isReg(i,j,k))return k; 
 }  

Предполагается что эта цифра все таки в каждой конкретной ситуации существует.

Главные вопросы:
1) Как это грамотно распарралелить. То есть как разумно распределить эти функции на машины.
2)Получается что все вычисления идут последовательно, то есть просчет
следующей клетки идет только после просчета предыдущей, ведь если выполнять на всех машинах
одновременно просчет, то появятся одинаковые клетки, нужна синхронизация, как ускорить и уп
ростить процесс вычислений? Ознакомился с RMI и решил что буду реализовывать на RMI, просто и
сердито. Прошу помочь с разрешением этих 2-х вопросов, буду оччень признателен и благодарен.
Огромное спасибо. 

Автор: sandello 3.5.2006, 11:42
На сколько я помню институтские разговоры про паралельные вычисления, метод реализации - это мелочь. Самое главное - суметь разделить вычисления на несколько слабосвязанных задач. Т.е. что бы обмен был сравнительно редок. В противном случае тормоза сетевого обмена сожрут все преимущества распределенных вычислений.

Применительно к текущей задаче. Возможные варианты распределения: У тебя есть какой-то головной цикл, и куча "дочерних" различной вложености. Цикл от 1 до 9. Делим задачу на два куска: запускаем параллельно два головных цикла
1. 1 <= i <= 5 
2. 6 <= j <= 9

Подобным образом можно бить задачу на любом вложенном цикле. Это вариант "в лоб". Скорее всего, если подумать, можно найти другой алгоритм решения (если он, конечно, есть) и построить более эффективное разделение задачи на куски.
 

Автор: zone51 3.5.2006, 22:00
sandello
Цитата

Делим задачу на два куска: запускаем параллельно два головных цикла
1. 1 <= i <= 5 
2. 6 <= j <= 9

Так понимаете в чем дело, я вообще запутался и сомневаюсь можно ли эту задачу вообще распарралелить. Ведь дело то в чем: параллельно то вычисляцца ниче не может, так как цифры в клетках заполняются одна за одной..Ну ладно, параллельно я вычислил значения в двух клетках, а как обеспечить несовпадения этих цифр? ведь одна часть приложения не знает что делает вторая..как быть?А ели разбить цикл на 2 кусак, ну допустим один кусок посчитает первую часть матрицы, второй вторую, и где гарантии что в столбцах, строках и регионах все цифры будут разные? Вот в чем сопрос. Если можно, я обращаюсь ко всем, поделитесь соображениями кто может..очень надо.Заранее огромное спасибо. 

Автор: sandello 4.5.2006, 06:41
Прежде, чем распараллеливать, просто реши задачу. Тут решения  я не увидел. 

Автор: jimur 5.5.2006, 06:14
Как это нельзя параллелить?
Берешь данную ячейку, ее строку и столбец и отправляешь на расчет
Результат - или точно число или варанты для ячеек
Отлично параллелится на 9 потоков.

Тебе алгоритм написать? smile
 

Автор: onsh76 5.5.2006, 10:00
В добавление к сказанному jimur:
предлагаю разбить бизнес логику на stateless - (там где не требуется тракировать статус отслеживаемой логики) и statefull(соотв-но наоборот). Сделай stateless компоненты распределенными, а statefull будет давать задания распр-ным компонентам по мере надобности и отслеживать результаты вычисления.  

Автор: zone51 5.5.2006, 12:21
jimur
Цитата

Берешь данную ячейку, ее строку и столбец и отправляешь на расчет
Результат - или точно число или варанты для ячеек
Отлично параллелится на 9 потоков.

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

p.s. А алгоритм писать не надо..просто я хочу просечь несколько логических фишек.

onsh76
Цитата

Сделай stateless компоненты распределенными, а statefull будет давать задания распр-ным компонентам по мере надобности и отслеживать результаты вычисления.  

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

Автор: jimur 5.5.2006, 20:44
ээх...
что-то типа этого:
Код

final byte[] allValues = new byte[9*9];
while (!isSolved()) {
for (int i =0; i<3;i++) {
for (int k =0; k<3;k++) {
byte[] column = new byte[3*9];
byte[] row = new byte[9*3];
byte[] current = new byte[3*3];
fillValues(i,k, column, row, current);// заполняем
byte[] result = sentToRemoteHostToSolve(column, row, current);// решаем на других хостах
}
collectResults(); // ждем и собираем решения
fillAllValues(); // заполняем результаты в общую матрицу значений
// повторяем до тех пор пока не будут известны все значения
}

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

Автор: zone51 5.5.2006, 21:19
jimur
Цитата

byte[] column = new byte[3*9];    
byte[] row = new byte[9*3];

 Извините нифига не понял, почему 27 элементов?
Цитата

byte[] result = sentToRemoteHostToSolve(column, row, current);

Неужели я так плохо знаю RMI? Я думал там просто пойдет разбиение задачи на подзадачи, и уже эти подзадачи по машинам..
Цитата

sentToRemoteHostToSolve

Это функция RMI или условное обозначение пользовательской функции? Спасибо. 

Автор: jimur 5.5.2006, 21:50
Цитата(zone51 @  5.5.2006,  21:19 Найти цитируемый пост)
Извините нифига не понял, почему 27 элементов?

Всего 9*9 = 81 элемент
При расчете блока 3*3 нужно учитывать строку и столбец в которые он попадает, соотвественно столбец из трех рядов чисел и строка из трех рядов.

Цитата(zone51 @  5.5.2006,  21:19 Найти цитируемый пост)
Неужели я так плохо знаю RMI? Я думал там просто пойдет разбиение задачи на подзадачи, и уже эти подзадачи по машинам..

Подзадачей и будет обработка данного набора данных. Итого можно обрабатывать на 9 машинах.

Цитата(zone51 @  5.5.2006,  21:19 Найти цитируемый пост)
Это функция RMI или условное обозначение пользовательской функции? 

Второе

Методы написать? ;)
 

Автор: zone51 6.5.2006, 13:12
jimur
Все, понял как вы делали, а скажите, разве теоретически нельзя по тому же принципу распарралелить на 81 машину? я не собираюся так делать, просто интересно.
И самый главный вопрос так это все те же "грабли", с которых я так и не могу слезть: посылаю я все 9 блоков одновременно?
Что значит ждем результатов и собираем значения? но ведь опять же, где гарантии того, что во всех строках и столбцах все цифры будут разные?
Цитата

final byte[] allValues = new byte[9*9];    
while (!isSolved()) {    
for (int i =0; i<3;i++) {    
for (int k =0; k<3;k++) {    
byte[] column = new byte[3*9];    
byte[] row = new byte[9*3];    
byte[] current = new byte[3*3];    
fillValues(i,k, column, row, current);// заполняем    
byte[] result = sentToRemoteHostToSolve(column, row, current);// решаем на других хостах    
}    
collectResults(); // ждем и собираем решения    
fillAllValues(); // заполняем результаты в общую матрицу значений    
// повторяем до тех пор пока не будут известны все значения    
}

Ну послал я все блоки, они вычислились, но ведь на все блоки я послал Исходные данные, без учета результата просчета других блоков.Как быть? Обьясните пожалуйста


 

Автор: Ivan Kolesnikov 7.5.2006, 06:46
Привет! Я понял идею jimur.
Он предлагает разбить задачу на 9 (на большее число нельзя) подзадач, решения которых не влияют друг на друга, далее получаем ответ от этих задач, объединяем его вместе и создаем новых 9 задач и т.д., если решение одной из подзадачи не может быть найдено, то производим откат.

Хотя возможно на некотором шаге нам удастся создать только меншьшее число не пересекающихся подзадач.

Разбивать нужно обяхательно так, чтобы решения не влияли друг на друга.

Например для приведенного примера можно искать следующие решения параллельно (выделены *)
Код

7.*25..98
..6....1*
...61*3..
9....1.*.
.*..8.4.9
..75*28.1
.94..3*..
*...4923.
61.*...4.
 

Автор: zone51 7.5.2006, 10:05
Ivan Kolesnikov
мысль перехватил, опробовал. все хорошо да вот загвоздка: что делать если в ходе вычисления очередной цифры оказалось, что эта цифра число 10, т е все цифры 1-9 есть либо в строке либо в столбце либо в регионе? Буду очень благодарен за помощь. Помогите если можно.  

Автор: jimur 8.5.2006, 23:39
Хорошая задачка  smile 
Решение ниже  smile 

Зачем выносить на удаленные машины то, что локально делается на 10-30ms  smile 

Код

public final class SudokuSolver extends AbstractBlocksTask {
    private static final int[][] TASK_BLOCKS_MAP =
            new int[][]{
                    {0, 1, 2, 3, 6}, {1, 0, 2, 4, 7}, {2, 0, 1, 5, 8},
                    {3, 4, 5, 0, 6}, {4, 3, 5, 1, 7}, {5, 3, 4, 2, 8},
                    {6, 7, 8, 0, 3}, {7, 6, 8, 1, 4}, {8, 6, 7, 2, 5},
            };

    public SudokuSolver(final Block[] blocks) {
        super(blocks); // 9
        if (blocks == null || blocks.length != 9) {
            throw new IllegalArgumentException();
        }
    }

    public static void main(final String[] args) {
        final long st = System.currentTimeMillis();
        final Block[] blocks = new Block[]{
                Block.buildBlock(5, 3, 0, 6, 0, 0, 0, 9, 8),
                Block.buildBlock(0, 7, 0, 1, 9, 5, 0, 0, 0),
                Block.buildBlock(0, 0, 0, 0, 0, 0, 0, 6, 0),
                Block.buildBlock(8, 0, 0, 4, 0, 0, 7, 0, 0),
                Block.buildBlock(0, 6, 0, 8, 0, 3, 0, 2, 0),
                Block.buildBlock(0, 0, 3, 0, 0, 1, 0, 0, 6),
                Block.buildBlock(0, 6, 0, 0, 0, 0, 0, 0, 0),
                Block.buildBlock(0, 0, 0, 4, 1, 9, 0, 8, 0),
                Block.buildBlock(2, 8, 0, 0, 0, 5, 0, 7, 9),
        };
        final SudokuSolver sudokuSolver = new SudokuSolver(blocks);
        final int result = sudokuSolver.process();
        if (result == 162) {
            sudokuSolver.printResult();
            System.out.println("Solved, processing time is " + (System.currentTimeMillis()-st) + " ms");
        } else {
            System.out.println("Error, result = " + result);
        }
    }

    private void printResult() {
        for (Block block : blocks) System.out.println(block);
    }

    protected void calculate() {
        final Task[] tasks = new Task[9];
        for (int i = 0; i < tasks.length; i++) {
            tasks[i] = new Task(new Block[]{blocks[TASK_BLOCKS_MAP[i][0]],
                    blocks[TASK_BLOCKS_MAP[i][1]], blocks[TASK_BLOCKS_MAP[i][2]],
                    blocks[TASK_BLOCKS_MAP[i][3]], blocks[TASK_BLOCKS_MAP[i][4]]});
        }

        for (Task task : tasks) task.process();

        for (int i = 0; i < tasks.length; i++) {
            final Task task = tasks[i];
            for (int k = 0; k < 5; k++) {
                final Block[] resultblocks = task.getBlocks();
                blocks[TASK_BLOCKS_MAP[i][k]].merge(resultblocks[k]);
            }
        }
    }
}

abstract class AbstractBlocksTask {
    Block[] blocks; //0-current; 1,2 - goriz ; 3,4 -vert

    protected AbstractBlocksTask(final Block[] blocks) {
        this.blocks = blocks;
    }

    public int process() {
        int prevCheckSum = sumCheckSums();
        int curCheckSum = 0;
        while (curCheckSum != prevCheckSum) {
            if (curCheckSum > 0) prevCheckSum = curCheckSum;
            calculate();
            curCheckSum = sumCheckSums();
        }
        return curCheckSum;
    }

    protected abstract void calculate();

    private int sumCheckSums() {
        int checkSum = 0;
        for (int i = 0; i < blocks.length; i++) checkSum += blocks[i].checkSum();
        return checkSum;
    }

    public final Block[] getBlocks() {
        return blocks;
    }
}

final class Block {
    private final byte[] locs;
    public static final int GORIZONTAL_MASK = 0x38;// 111000
    public static final int VERTICAL_MASK = 0x7;// 000111
    private static final int[] LINE_MASKS = new int[]{0x1, 0x2, 0x4, 0x8, 0x10, 0x20};
    private static final int[] HELP_LINE_MASKS = new int[]{0x38, 0x38, 0x38, 0x7, 0x7, 0x7,};

    protected Block(final byte[] locs) {
        this.locs = locs;
        for (int i = 0; i < locs.length; i++) {
            if (locs[i] == 0) locs[i] = 0x3f;
        }
    }

    public final boolean isFull() {
        boolean b = true;
        for (int i = 0; b && i < locs.length; i++) b = b && isDefined(locs[i]);
        return b;
    }

    public static boolean isDefined(final int loc) {
        return bitSum(loc & 0x7) == 1 && bitSum(loc & 0x38) == 1;
    }

    private static int bitSum(final int loc) {
        int r = 0;
        for (int i = 0; i < 6; i++) r += (loc >> i) & 1;
        return r;
    }

    public String toString() {
        final byte[] bytes = new byte[9];
        for (int i = 0; i < locs.length; i++) {
            if (isDefined(locs[i])) {
                bytes[((locs[i] & 0x38) >> 4) * 3 + ((locs[i] & 0x7) >> 1)] = (byte) (i + 1);
            }
        }
        String s = "";
        for (int i = 0; i < bytes.length; i++) {
            s += bytes[i];
            if (((i + 1) % 3) == 0) s += "\n";
        }
        return s;
    }

    // to test
    byte getLoc(final int num) {
        return locs[num - 1];
    }

    public int checkSum() {
        int sum = 0;
        for (int i = 0; i < locs.length; i++) sum += bitSum(locs[i]);
        return sum;
    }

    public static Block buildBlock(final int... nums) {
        final byte[] locs = new byte[9];
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > 0) {
                locs[nums[i] - 1] = (byte) ((((i % 3 == 0 ? 1 : ((i % 3) << 1)) | ((i / 3 == 0 ? 1 : (i / 3 << 1)) << 3))));
            }
        }
        return new Block(locs);
    }

    public static void intersect(final int mask, final Block... blocks) {
        for (int k = 0; k < blocks.length; k++) {
            final Block b1 = blocks[k];
            for (Block b2 : blocks) {
                if (b1 != b2) {
                    for (int i = 0; i < 9; i++) {
                        if (bitSum(b2.locs[i] & mask) == 1) {
                            b1.locs[i] = (byte) (~(b2.locs[i] & mask) & b1.locs[i]);
                        } else if (bitSum(b1.locs[i] & mask) == 1) {
                            b2.locs[i] = (byte) (~(b1.locs[i] & mask) & b2.locs[i]);
                        }
                    }
                }
            }
        }
        for (Block b1 : blocks) b1.fillLine();
    }

    private void fillLine() {
        for (int i = 0; i < LINE_MASKS.length; i++) {
            final int lineMask = LINE_MASKS[i];
            final int[] alts = new int[9];
            final int altCounter = fillAlts(lineMask, alts);
            processAlts(i, altCounter, alts);
        }
    }

    private int fillAlts(final int lineMask, final int[] alts) {
        int altCounter = 0;
        for (int k = 0; k < locs.length; k++) {
            if (bitSum(locs[k] & lineMask) == 1) {
                alts[altCounter] = k;
                altCounter++;
            }
        }
        return altCounter;
    }

    private void processAlts(final int lineIndex, final int altCounter, final int[] alts) {
        final int[] defined = new int[9];
        int defCounter = 0;
        final int[] undefineds = new int[2];
        undefineds[0] = -1;
        for (int k = 0; k < alts.length && k < altCounter; k++) {
            if (isDefined(locs[alts[k]])) {
                defined[defCounter] = alts[k];
                defCounter++;
            } else {
                undefineds[undefineds[0] == -1 ? 0 : 1] = alts[k];
            }
        }
        if (altCounter == 3) {
            if (defCounter == 2) {
                locs[undefineds[0]] = (byte) (LINE_MASKS[lineIndex] | (HELP_LINE_MASKS[lineIndex] ^ locs[defined[0]] ^ locs[defined[1]]));
            } else if (defCounter == 1) {
                final int undefIndex = bitSum(locs[undefineds[0]] & HELP_LINE_MASKS[lineIndex]) == 2 ? 0 : 1;
                locs[undefineds[undefIndex]] = (byte) (LINE_MASKS[lineIndex] |
                        ((locs[undefineds[undefIndex]] ^ locs[defined[0]]) & HELP_LINE_MASKS[lineIndex]));
            }
        } else if (defCounter == 3) {
            for (int i = 0; i < locs.length; i++) {
                if (!isDefined(locs[i])) locs[i] = (byte) (locs[i] & ~LINE_MASKS[lineIndex]);
            }
        }
    }

    public boolean isSolved(final int num) {
        return isDefined(locs[num - 1]);
    }

    public void merge(final Block b2) {
        for (int i = 0; i < locs.length; i++) locs[i] = (byte) (locs[i] & b2.locs[i]);
    }
}

final class Task extends AbstractBlocksTask {
    public Task(final Block[] blocks) {
        super(blocks);        //0-current; 1,2 - goriz ; 3,4 -vert
    }

    protected void calculate() {
        Block.intersect(Block.GORIZONTAL_MASK, blocks[0], blocks[1], blocks[2]);
        Block.intersect(Block.VERTICAL_MASK, blocks[0], blocks[3], blocks[4]);
    }
}


zone51, с тебя причитается ;) 

Автор: zone51 8.5.2006, 23:49
jimur
Цитата

zone51, с тебя причитается ;) 

Само собой
Цитата

Зачем выносить на удаленные машины то, что локально делается на 10-30ms

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

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

Автор: jimur 9.5.2006, 00:34
Так это же рутина ...

1. делаем сериализуемой задачу:
Код

final class Task extends AbstractBlocksTask implements Serializable {

2. заходим сюда и внимательно читаем
http://java.sun.com/docs/books/tutorial/rmi/index.html
3. создаем удаленный процессор
Код

public class RemoteProcessor implements Remote {
    public static void main(final String[] args) {
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new RMISecurityManager());
        }
        try {
            final String name = "//Sudoku/Solver";
            final SudokuSolver solver = (SudokuSolver) Naming.lookup(name);
            solver.add(new RemoteProcessor());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public final int process(final Task task) {
        return task.process();
    }
}

4. из солвера делаем удаленный сервер
Код

public final class SudokuSolver extends AbstractBlocksTask implements Remote {
...
    private final List<RemoteProcessor> remoteProcessors = new ArrayList<RemoteProcessor>(9);
    public void add(final RemoteProcessor remoteProcessor) {
        remoteProcessors.add(remoteProcessor);
    }

    public static void main(final String[] args) {
        ...
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new RMISecurityManager());
        }
        String name = "//Sudoku/Solver";
        try {
            Naming.rebind(name, sudokuSolver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
...
//        for (Task task : tasks) task.process();
        remoteProcess(tasks);
    private void remoteProcess(final Task[] tasks) {
        // тут делишь задачи на потоки и запускашь remoteProcessor.process(task)
        // ну и дожидаешься всех ответов
    }

...
}


  

Автор: zone51 9.5.2006, 01:24
Уважаемый jimur, спасибо огромное, мне это очень помогло, но все таки, подскажите пожалуйста, Как разбивать задачу на потоки, алгоритм, вот в чем вопрос. Огромное спасибо.
Цитата

может подскажите что делать со случаем 10-ки если на каждом шаге выбираются независимые клетки из каждого района?
 
Как правильно распарралелить задачу, вот в чем вопрос, я просто застрял в начале smile smile 
 

Автор: jimur 9.5.2006, 12:07
Так в алгоритме уже заложено это разбиение.
Мы имеем 9 _независимых_ задач, которые можно испольнять параллельно.

Код с потоками попозже кину - времени пока нет. 

Автор: zone51 9.5.2006, 12:25
Цитата

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

Спасибо за код,и просто намекните Где в алгоритме это разбиение?
Ну вот на чем я застрял: 
Принцип разбиения: на каждом щаге выбираются из каждого района по 1-й независимой клетке(где возможно), потом это парралельно вычисляется, но на каком то шаге оказывается, что в такую-то клетку нельзя поставить цифру, все уже есть, как быть?Мне важен принцип, вы и так многое для меня сделали, но мне важен алгоритм распарралеливагия "на пальцах" коротко. Огромное спасибо. Что с 10-й делать, вот в чем вопрос.   

Автор: jimur 9.5.2006, 20:46
Цитата(zone51 @  9.5.2006,  12:25 Найти цитируемый пост)
Спасибо за код,и просто намекните Где в алгоритме это разбиение?

Тут это разбиение.
1 .Создаем 9 независимых задач
2. Выполняем эти задачи (в этом коде последовательно)
3. Собираем результаты
Код

protected void calculate() {
        final Task[] tasks = new Task[9];
        for (int i = 0; i < tasks.length; i++) { // 1. Создаем 9 независимых задач 
            tasks[i] = new Task(new Block[]{blocks[TASK_BLOCKS_MAP[i][0]],
                    blocks[TASK_BLOCKS_MAP[i][1]], blocks[TASK_BLOCKS_MAP[i][2]],
                    blocks[TASK_BLOCKS_MAP[i][3]], blocks[TASK_BLOCKS_MAP[i][4]]});
        }
        for (Task task : tasks) task.process();// 2. Выполняем эти задачи (в этом коде последовательно)
        for (int i = 0; i < tasks.length; i++) {// 3. Собираем результаты
            final Task task = tasks[i];
            for (int k = 0; k < 5; k++) {
                final Block[] resultblocks = task.getBlocks();
                blocks[TASK_BLOCKS_MAP[i][k]].merge(resultblocks[k]);
            }
        }
    }

Цитата(zone51 @  9.5.2006,  12:25 Найти цитируемый пост)
Принцип разбиения: на каждом щаге выбираются из каждого района по 1-й независимой клетке(где возможно), потом это парралельно вычисляется, но на каком то шаге оказывается, что в такую-то клетку нельзя поставить цифру, все уже есть, как быть?Мне важен принцип, вы и так многое для меня сделали, но мне важен алгоритм распарралеливагия "на пальцах" коротко. Огромное спасибо. Что с 10-й делать, вот в чем вопрос.  

При _внимательном_ изучении алоритма видно, что ситуация с 10-кой в принципе невозможна, т.к. оперируем массивом из 9 элементов, в который в виде 6 бит закодированы возможные строки/столбцы для данной цифры в рамках данного блока.

Еще есть вопросы? smile
 

Автор: zone51 16.5.2006, 17:59
В общем спасибо всем,с алгоритмом я сення с преподом вопрос решил, все свелось к полному перебору, то есть просчитываем всю матрицу для каждой клетки причем при цифрах от 1 до 9. Ужасть! smile Теперь вопросы общего характера, для RMI нужен сервер? то есть вот в книге написано, допустим приложение распределенное WeatherService загружает информацию о погоде с различных источников. А как в моем случае? сделать удаленные объекты, удаленный сервер и клиентское приложение? А сервер значит регулирует эти запросы? Спасибо.  

Автор: ALKS 16.5.2006, 18:19
для RMI не нужен апп-сервер, если ты об этом. сам напишеш приложение которое будет играть роль сервера smile 

Автор: zone51 16.5.2006, 18:20
А уже это приложение распределяет кто куда на удаленные машины? 

Автор: ALKS 16.5.2006, 20:09
Цитата(zone51 @ 16.5.2006,  18:20)
А уже это приложение распределяет кто куда на удаленные машины?

или удаленные машины будут спрашиватьу  него чего им делать smile 
полная свобода действий - free art smile 

Автор: jimur 16.5.2006, 20:51
Цитата(zone51 @  16.5.2006,  17:59 Найти цитируемый пост)
В общем спасибо всем,с алгоритмом я сення с преподом вопрос решил, все свелось к полному перебору, то есть просчитываем всю матрицу для каждой клетки причем при цифрах от 1 до 9. Ужасть! smile 

Офтоп: а чем предложенный алгоритм не устроил?

Цитата(zone51 @  16.5.2006,  17:59 Найти цитируемый пост)
А как в моем случае? сделать удаленные объекты, удаленный сервер и клиентское приложение? А сервер значит регулирует эти запросы? 

Удаленный вычислитель: регистрируется в сервере, выполняет задачи
Сервер + GUI: регистрирует вычислители, получает общую задач от пользователя, создает задачи и раскидывает по вычислителям, собирает результат, отображает пользователю. (сервер пишешь как в указанном ранее туториале безо свяких апп серверов) 

Автор: zone51 16.5.2006, 20:59
Цитата

Офтоп: а чем предложенный алгоритм не устроил?

Препод не смог разобрацца в алгоритме..если честно я тоже..ведь вы так и не сказали самое главное: как распарралелить задачу. Поэтому все и стояло. Вам огромное спасибо, я на ваших исходниках понял сколько мне еще учить яву smile Огромное спасибо.
 А несчет сервера ну не совсем понятно зачем он, только для управления и синхронизации?
Ну да ладно. Значит сервер это обычный класс в котором я прописываю методы доступа к удаленным объектам, сервет конектицца к обьектам и запрашивает методы? Не совсем понятна картина разворачивания этого всего..я читал про rmiregistry, rmic и тд, но это надо делать на всех удаленных машинах? вносить в реестр и т д..Непонятно. Спасибо всем кто откликнется. 

Автор: jimur 16.5.2006, 21:21
Цитата(zone51 @  16.5.2006,  20:59 Найти цитируемый пост)
Препод не смог разобрацца в алгоритме..если честно я тоже..ведь вы так и не сказали самое главное: как распарралелить задачу. 

и эти люди учат вас программировать .... smile)
алгоритм простейший - делим задачу на 9 подзадач: 
каждая подзадача это:
данные: блок (3х3) + соседние вертикальные и горизонтальные блоки
алгоритм (high-level): проставить числа исходя из имеющихся данных
потом результаты мержим и опять делим на подзадачи, так пока не решим 

Цитата(zone51 @  16.5.2006,  20:59 Найти цитируемый пост)
 А несчет сервера ну не совсем понятно зачем он, только для управления и синхронизации?
Ну да ладно. Значит сервер это обычный класс в котором я прописываю методы доступа к удаленным объектам, сервет конектицца к обьектам и запрашивает методы? Не совсем понятна картина разворачивания этого всего..я читал про rmiregistry, rmic и тд, но это надо делать на всех удаленных машинах? вносить в реестр и т д..Непонятно. Спасибо всем кто откликнется. 

Сервер (у него remote метод addRemoteProcessor) регистрирует себя в rmiregistry (запускается на одной машине). Вычислители работают как клиенты - находят в rmiregistry сервер, и регистрируются в сервере.
Сервер проходится по вычислителям, раздает задачи (вызывает remote метод process(Task task) у вычислителей), сливает результаты. 

Автор: zone51 16.5.2006, 21:33
Цитата

и эти люди учат вас программировать .... )

гм..наверное да..только вот репутация у него почти мировая...наверное чел просто не хотел копацца, сказав что главное Rmi а не задача
Цитата

алгоритм простейший - делим задачу на 9 подзадач: 
каждая подзадача это:
данные: блок (3х3) + соседние вертикальные и горизонтальные блоки
алгоритм (high-level): проставить числа исходя из имеющихся данных
потом результаты мержим и опять делим на подзадачи, так пока не решим 

то есть берем "угол", просчитываем его, смешиваем с исходной матрицей и т д..а не слишком ли просто? smile Спасибо.  

Автор: jimur 16.5.2006, 22:17
Цитата(zone51 @  16.5.2006,  21:33 Найти цитируемый пост)
то есть берем "угол", просчитываем его, смешиваем с исходной матрицей и т д..а не слишком ли просто? smile Спасибо.   

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

Автор: zone51 23.5.2006, 13:44
Товарищи, спасибо всем, а можно мне узнать какими компонентами J2SE можно реализовать квадратную матрицу? Пробовал JTable, но там никак нельзя поменять размеры ячеек. Спасибо. 

Автор: jimur 24.5.2006, 08:12
это тебе в java gui постить надо 

Автор: zone51 26.5.2006, 16:33
Товарищи, а не подскажете, почему то не срабатывает фрагмент кода
Цитата

public static void main(String[] args)
 {
  try 
  {
   String name = "sudokuServer";    
   sudokuRemoteImpl pr=new sudokuRemoteImpl();
   sudokuServer server = (sudokuServer)Naming.lookup(name);    
   server.comeon(pr);
  }
  catch (Exception e) 
  {
   e.printStackTrace();    
  }
 }


Хотя метод comeon описан правильно

Цитата

public void comeon(sudokuRemoteImpl sud)
 {
  f.accessLabel("New Process");
  remoteProcessors.add(sud);
 };


Выдает ошибку:
Цитата

C:\prog1\Sudoku>java sudokuRemoteImpl
java.lang.IllegalArgumentException: argument type mismatch
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
        at sun.rmi.transport.Transport$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.rmi.transport.Transport.serviceCall(Unknown Source)
        at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
        at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source)
        at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
        at sun.rmi.server.UnicastRef.invoke(Unknown Source)
        at sudokuServerImpl_Stub.comeon(Unknown Source)
        at sudokuRemoteImpl.main(sudokuRemoteImpl.java:49)

Спасибо огромное.   

Автор: powerOn 28.5.2006, 14:00
Цитата(zone51 @  23.5.2006,  14:44 Найти цитируемый пост)
Товарищи, спасибо всем, а можно мне узнать какими компонентами J2SE можно реализовать квадратную матрицу? Пробовал JTable, но там никак нельзя поменять размеры ячеек. Спасибо.  


Это почему это нельзя?

Код

import java.util.Enumeration;
import javax.swing.table.TableColumn;

public class NewJFrame extends javax.swing.JFrame {
    

    public NewJFrame() {
        initComponents();
        
    }
    
    private void initComponents() {
        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jSlider1 = new javax.swing.JSlider();
        jSlider2 = new javax.swing.JSlider();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        jTable1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        jTable1.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
        jScrollPane1.setViewportView(jTable1);

        getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);

        jSlider1.setMaximum(200);
        jSlider1.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jSlider1StateChanged(evt);
            }
        });

        getContentPane().add(jSlider1, java.awt.BorderLayout.NORTH);

        jSlider2.setMaximum(200);
        jSlider2.setOrientation(javax.swing.JSlider.VERTICAL);
        jSlider2.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jSlider2StateChanged(evt);
            }
        });

        getContentPane().add(jSlider2, java.awt.BorderLayout.EAST);

        pack();
    }

    private void jSlider2StateChanged(javax.swing.event.ChangeEvent evt) {
       jTable1.setRowHeight(jSlider2.getValue());
    }

    private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt) {
        Enumeration e = jTable1.getColumnModel().getColumns();
       while(e.hasMoreElements()) {
           ((TableColumn) e.nextElement()).setPreferredWidth(jSlider1.getValue());
       }
 
    }
    
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new NewJFrame().setVisible(true);
            }
        });
    }
    
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JSlider jSlider1;
    private javax.swing.JSlider jSlider2;
    private javax.swing.JTable jTable1;
    
}

 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)