Professional Documents
Culture Documents
Huong Dan Chay MapReduceShortestPath
Huong Dan Chay MapReduceShortestPath
Đỉnh bắt đầu (Source Node) là đỉnh mà tại đó ta tìm đường đi ngắn nhất từ đỉnh
đó qua tất cả các đỉnh còn lại.
a. Tổ chức danh sách kề ban đầu như sau:
{Node Number, Node Weight, Node Status} TAB {Adjacent Node, Edge Weight} TAB {Adjacent Node, Edge Weight} ...
Trong đó:
Node Weight = 0 đối với đỉnh bắt đầu.
Node Weight = INFINITY cho tất cả các đỉnh còn lại
Node Status = UNDISCOVERED cho tất cả các đỉnh.
Adjacent Node: Đỉnh kề với đỉnh Node Number
Edge Weight : Trọng số của cạnh nối giữa 2 đỉnh Node Number và Adjacent Node.
Như vậy, theo như đồ thị trên thì danh sách kề sẽ được khởi tạo như sau:
Source Node: It is the node from which we are attempting to find the shortest path to
all other nodes.
Node Count: 10
Edge Count: 20
Adjacency List:
{Node Number, Node Weight, Node {Adjacent Node, {Adjacent Node, {Adjacent Node, ….
Status} Edge Weight} Edge Weight} Edge Weight}
1
{1,0,UNDISCOVERED} {2,40} {3,8} {4,10}
{2,INFINITY,UNDISCOVERED} {5,6} {7,10}
{3,INFINITY,UNDISCOVERED} {2,4} {4,12} {6,2}
{4,INFINITY,UNDISCOVERED} {6,1}
{5,INFINITY,UNDISCOVERED} {3,2} {6,2} {7,4}
{6,INFINITY,UNDISCOVERED} {8,4} {9,3}
{7,INFINITY,UNDISCOVERED} {8,20} {10,1}
{8,INFINITY,UNDISCOVERED} {5,0} {10,20}
{9,INFINITY,UNDISCOVERED} {4,6} {10,2}
{Node Number, Node Weight, Node {Adjacent Node, {Adjacent Node, {Adjacent Node, ….
Status} Edge Weight} Edge Weight} Edge Weight}
{1,0,DISCOVERED,1} {2,40} {3,8} {4,10}
{2,12,UNDISCOVERED,1-3} {5,6} {7,10}
{3,8,DISCOVERED,1} {2,4} {4,12} {6,2}
{4,10,DISCOVERED,1} {6,1}
{5,46,UNDISCOVERED,1-2} {3,2} {6,2} {7,4}
{6,10,UNDISCOVERED,1-3} {8,4} {9,3
{7,50,UNDISCOVERED,1-2} {8,20} {10,1}
{8,INFINITY,UNDISCOVERED} {5,0} {10,20}
{9,INFINITY,UNDISCOVERED} {4,6} {10,2}
2
Intermediate Adjacency List Format:
{Node Number,Node Weight,Node Status,Path} TAB {Adjacent Node, Edge Weight} TAB {Adjacent
Node, Edge Weight} ...
Node Number = From Node Number (For all Nodes)
Node Weight = 0 (For the Source Node)
Minimum weight it takes in reaching from the Source Node to the From Node
(For other Nodes)
Node Status = UNDISCOVERED (For Nodes that are not Expanded)
DISCOVERED (For Nodes that are Expanded)
Path = The path from the Source Node to the From Node
Adjacent Node = Adjacent Node Number with an Edge from the From Node
Edge Weight = Weight of the Edge from the From Node to the Adjacent Node
a) Node Weight mới = Node Weight cũ + trọng số của cạnh kề (Edge Weight)
b) Chọn mapper output có key là node kề với source node.
c) Gán cho các Node cần xử lý trạng thái UNDISCOVERED: Node Status =
UNDISCOVERED
Hàm Reduce có nhiệm vụ tổng hợp các cặp <key, value> sau khi chạy hàm Map. Các
key giống nhau được sắp xếp chạy trong cùng một Reduce.
1) Khởi tạo một newValue
2) Ứng với mỗi Key, khi value còn giá trị:
Lấy dữ liệu cho newValue
4
Bước lặp 1:
Mapper Output [Trước khi sắp xếp, gộp nhóm]: Hình ảnh đồ thị minh họa
{1,0,DISCOVERED,1} {2,40} {3,8} {4,10}
{2,40,UNDISCOVERED,1}
{3,8,UNDISCOVERED,1}
{4,10,UNDISCOVERED,1}
{2,INFINITY,UNDISCOVERED} {5,6} {7,10}
{3,INFINITY,UNDISCOVERED} {2,4} {4,12} {6,2}
{4,INFINITY,UNDISCOVERED} {6,1}
{5,INFINITY,UNDISCOVERED} {3,2} {6,2} {7,4}
{6,INFINITY,UNDISCOVERED} {8,4} {9,3}
{7,INFINITY,UNDISCOVERED} {8,20}{10,1}
{8,INFINITY,UNDISCOVERED} {5,0} {10,20}
{9,INFINITY,UNDISCOVERED} {4,6} {10,2}
Bước lặp 2:
Mapper Input:
{1,0,DISCOVERED,1} {2,40} {3,8} {4,10}
{2,40,UNDISCOVERED,1} {5,6} {7,10}
{3,8,UNDISCOVERED,1} {2,4} {4,12} {6,2}
{4,10,UNDISCOVERED,1} {6,1}
{5,INFINITY,UNDISCOVERED} {3,2} {6,2} {7,4}
{6,INFINITY,UNDISCOVERED} {8,4} {9,3}
{7,INFINITY,UNDISCOVERED} {8,20} {10,1}
{8,INFINITY,UNDISCOVERED} {5,0} {10,20}
{9,INFINITY,UNDISCOVERED} {4,6} {10,2}
5
{6,11,UNDISCOVERED,1-4}
{6,INFINITY,UNDISCOVERED} {8,4} {9,3}
{7,50,UNDISCOVERED,1-2}
{7,INFINITY,UNDISCOVERED} {8,20}{10,1}
{8,INFINITY,UNDISCOVERED} {5,0} {10,20}
{9,INFINITY,UNDISCOVERED} {4,6} {10,2}
Bước lặp 3:
6
Final Output:
The Path in each Key-Value Pair is the Weighted Shortest Path from the Source Node
[0] to the Node in the Key.
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import java.io.IOException;
import java.util.Iterator;
import java.util.Arrays;
import org.apache.hadoop.mapred.MapReduceBase;
import org.apache.hadoop.mapred.Mapper;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.mapred.Reducer;
import org.apache.hadoop.mapred.Partitioner;
7
private static final int MAXIMUM_SOURCE_NODE_TOKENS = 4;
public static final int INDEX_SOURCE_NODE_NUMBER = 0;
public static final int INDEX_SOURCE_NODE_WEIGHT = 1;
private static final int INDEX_SOURCE_NODE_STATUS = 2;
private static final int INDEX_SOURCE_NODE_PATH = 3;
private Text emptyText = new Text();
@Override
public void map(Text key, Text value, OutputCollector<Text, Text> output, Reporter
reporter) throws IOException
{
String[] sourceNodeDetails = key.toString().substring(1, key.toString().length() -
1).split(",");
if (sourceNodeDetails.length >= MINIMUM_SOURCE_NODE_TOKENS
&& !sourceNodeDetails[INDEX_SOURCE_NODE_WEIGHT].equalsIgnoreCase(INFINITY)
&& !sourceNodeDetails[INDEX_SOURCE_NODE_STATUS].equalsIgnoreCase(DISCOVERED))
{
String currentPath = "";
if (sourceNodeDetails.length == MAXIMUM_SOURCE_NODE_TOKENS)
{
currentPath = sourceNodeDetails[INDEX_SOURCE_NODE_PATH];
}
currentPath += (currentPath.length() == 0 ? "" : "-") +
sourceNodeDetails[INDEX_SOURCE_NODE_NUMBER];
if (value.toString().trim().length() > 0)
{
String[] tokens = value.toString().trim().split("\t");
String[][] adjacentNodeDetails = new String[tokens.length][2];
for (int index = 0; index < tokens.length; index++)
{
adjacentNodeDetails[index] = tokens[index].substring(1, tokens[index].length()
- 1).split(",");
}
int sourceNodeWeight =
Integer.parseInt(sourceNodeDetails[INDEX_SOURCE_NODE_WEIGHT]);
for (int index = 0; index < tokens.length; index++)
{
int number = sourceNodeWeight + Integer.parseInt(adjacentNodeDetails[index]
[1]);
output.collect(new Text("{" + adjacentNodeDetails[index][0] + "," +
Integer.toString(number) + "," + UNDISCOVERED + "," + currentPath + "}"), emptyText);
reporter.incrCounter(ShortestPath.CUSTOM_COUNTERS,
ShortestPath.NUMBER_OF_UNDISCOVERED_NODES_TO_BE_PROCESSED, 1);
}
}
}
else
{
output.collect(key, value);
}
}
}//AlgorithmMapper
8
{
@Override
public void reduce(Text key, Iterator<Text> values, OutputCollector<Text, Text> output,
Reporter reporter) throws IOException
{
int index = 0;
String newValue = "";
while (values.hasNext())
{
if (index > 0)
{
newValue += "\t";
}
newValue += values.next().toString();
}
output.collect(key, new Text(newValue));
}
}//AlgorithmReducer
@Override
public int run(String[] args) throws Exception
{
int iteration = 0;
long toBeProcessed = 0;
boolean finalRun = false;
String inputPath = args[0];
String outputPath = args[1];
do
{
JobConf conf = new JobConf(getConf(), ShortestPath.class);
conf.setJobName(this.getClass().getName());
9
conf.setInputFormat(KeyValueTextInputFormat.class);
conf.setMapperClass(AlgorithmMapper.class);
conf.setOutputKeyComparatorClass(AlgorithmOutputKeyComparator.class);
conf.setOutputValueGroupingComparator(AlgorithmOutputValueGroupingComparator.class);
conf.setPartitionerClass(AlgorithmPartitioner.class);
conf.setReducerClass(AlgorithmReducer.class);
if (finalRun)
{
conf.setNumReduceTasks(1);
}
conf.setMapOutputKeyClass(Text.class);
conf.setMapOutputValueClass(Text.class);
conf.setOutputKeyClass(Text.class);
conf.setOutputValueClass(Text.class);
RunningJob job = JobClient.runJob(conf);
inputPath = outputPath + "-" + iteration;
iteration++;
toBeProcessed = job.getCounters().findCounter(CUSTOM_COUNTERS,
NUMBER_OF_UNDISCOVERED_NODES_TO_BE_PROCESSED).getValue();
finalRun = (toBeProcessed == 0 && !finalRun);
}
while (toBeProcessed > 0 || finalRun);
return 0;
}
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
@Override
public int compare(WritableComparable wc1, WritableComparable wc2)
{
String compositeKey1 = ((Text) wc1).toString().trim();
String compositeKey2 = ((Text) wc2).toString().trim();
10
String[] nodeDetails1 = compositeKey1.substring(1, compositeKey1.length() -
1).split(",");
String[] nodeDetails2 = compositeKey2.substring(1, compositeKey2.length() -
1).split(",");
return returnValue;
}
}
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
11
public class AlgorithmOutputValueGroupingComparator extends WritableComparator
{
public AlgorithmOutputValueGroupingComparator()
{
super(Text.class, true);
}
@Override
public int compare(WritableComparable wc1, WritableComparable wc2)
{
String compositeKey1 = ((Text) wc1).toString().trim();
String compositeKey2 = ((Text) wc2).toString().trim();
Xóa thư mục /inputXYZ nếu đã có, tạo mới và chép dữ liệu vào
C:\hadoop\ShortestPath> hadoop fs -rm -r /inputXYZ
C:\hadoop\ShortestPath> hadoop fs -mkdir /inputXYZ
C:\hadoop\ShortestPath> hadoop fs -put input.txt /inputXYZ
C:\hadoop\ShortestPath> hadoop fs -ls /inputXYZ
Chạy chương trình Mapreduce với dữ liệu trong thư mục /inputXYZ, kết quả xuất ra
/outputXYZ
C:\hadoop\ShortestPath> hadoop jar ShortestPathXYZ.jar ShortestPath
/inputXYZ /outputXYZ
Quá trình Map/Reduce sẽ lặp đi lặp lại nhiều lần. Kết quả của Map sẽ là input cho
Reduce.
Xem kết quả trong /outputXYZ
c:\hadoop\MapReduceShortestPath>hadoop fs -ls /
Found 10 items
drwxr-xr-x - Administrator supergroup 0 2020-06-20 09:41 /inputXYZ
drwxr-xr-x - Administrator supergroup 0 2020-06-20 10:15 /outputXYZ
drwxr-xr-x - Administrator supergroup 0 2020-06-20 10:12 /outputXYZ-0
drwxr-xr-x - Administrator supergroup 0 2020-06-20 10:12 /outputXYZ-1
drwxr-xr-x - Administrator supergroup 0 2020-06-20 10:13 /outputXYZ-2
drwxr-xr-x - Administrator supergroup 0 2020-06-20 10:13 /outputXYZ-3
drwxr-xr-x - Administrator supergroup 0 2020-06-20 10:14 /outputXYZ-4
drwxr-xr-x - Administrator supergroup 0 2020-06-20 10:14 /outputXYZ-5
drwxr-xr-x - Administrator supergroup 0 2020-06-20 10:15 /outputXYZ-6
drwx------ - Administrator supergroup 0 2020-05-30 20:45 /tmp
13
{9,13,DISCOVERED,1-3-6-9} {4,6} {10,2}
{10,15,DISCOVERED,1-3-6-9-10}
4. Bài tập
Mô tả quá trình thực hiện sử dụng giải thuật MapReduce với nhiều bộ dữ liệu khác.
theo các bước như sau:
a) Mô tả cấu trúc dữ liệu sử dụng trong chương trình
b) Tổ chức dữ liệu đầu vào
c) Quá trình Map/Reduce. Minh họa bằng kết quả trung gian và đồ thị
14
----------------------------------------------------------
15