অন্যান্য প্ল্যাটফর্মগুলিতে কীভাবে এটি যোগাযোগ করা যেতে পারে তা চিত্রিত করার জন্য আমি R
কিছুটা উপায়হীনভাবে কোডেড এমন একটি প্রস্তাব দেব R
।
R
(পাশাপাশি কিছু অন্যান্য প্ল্যাটফর্ম, বিশেষত যারা কার্যকরী প্রোগ্রামিং শৈলীর পক্ষে রয়েছে) উদ্বেগটি হ'ল ক্রমাগত একটি বড় অ্যারে আপডেট করা খুব ব্যয়বহুল হতে পারে। পরিবর্তে, তারপরে, এই অ্যালগরিদম তার নিজস্ব ব্যক্তিগত ডেটা কাঠামো বজায় রাখে যার মধ্যে (ক) এ পর্যন্ত পূরণ করা সমস্ত কক্ষ তালিকাভুক্ত করা হয়েছে এবং (খ) সমস্ত নির্বাচিত ঘর নির্বাচন করা হবে (ভরাট কোষের ঘেরের চারপাশে) তালিকাভুক্ত. যদিও এই ডেটা কাঠামোটি হেরফের করা সরাসরি অ্যারেতে ইনডেক্সিংয়ের চেয়ে কম দক্ষ, পরিবর্তিত ডেটাটিকে একটি ছোট আকারে রেখে, সম্ভবত এটি কম গণনার সময় নেয়। (এটির জন্যও অনুকূলিতকরণের জন্য কোনও প্রচেষ্টা করা হয়নি R
। রাজ্যের ভেক্টরদের প্রাক-বরাদ্দের কিছু সময় কার্যকর করার সময় সাশ্রয় করা উচিত, যদি আপনি কাজ চালিয়ে যেতে চান তবে R
।)
কোডটি মন্তব্য করা হয়েছে এবং পড়ার জন্য সোজা হওয়া উচিত। যতটা সম্ভব অ্যালগরিদমকে সম্পূর্ণ করতে, ফলাফলের প্লট করা ছাড়া এটি কোনও অ্যাড-অন ব্যবহার করে না। একমাত্র জটিল অংশটি দক্ষতা এবং সরলতার জন্য এটি 1 ডি সূচকগুলি ব্যবহার করে 2D গ্রিডে সূচক পছন্দ করে। neighbors
কোনও কক্ষের অ্যাক্সেসযোগ্য প্রতিবেশী কী হতে পারে তা নির্ধারণ করার জন্য ফাংশনে একটি রূপান্তর ঘটে যা 2D সূচক প্রয়োজন এবং তারপরে তাদের 1D সূচীতে রূপান্তর করে। এই রূপান্তরটি আদর্শ, সুতরাং অন্যান্য জিআইএস প্ল্যাটফর্মে আপনি কলাম এবং সারি সূচকগুলির ভূমিকাগুলি বিপরীত করতে চাইতে পারেন তা উল্লেখ করা ছাড়া আমি এ বিষয়ে আরও মন্তব্য করব না। ( R
কলাম সূচকগুলি করার আগে সারি সূচী পরিবর্তন হয়))
উদাহরণস্বরূপ, এই কোডটি গ্রিডের x
প্রতিনিধিত্বকারী একটি গ্রিড এবং অ্যাক্সেসযোগ্য পয়েন্টগুলির নদীর মতো বৈশিষ্ট্য গ্রহণ করে, সেই গ্রিডের একটি নির্দিষ্ট স্থানে (5, 21) শুরু হয় (নদীর নীচের বাঁকের নিকটে) এবং এটিকে এলোমেলোভাবে প্রসারিত করে 250 পয়েন্টগুলি coverেকে রাখে । মোট সময়সীমা 0.03 সেকেন্ড। (যখন অ্যারের আকারটি 10,000 থেকে 3000 সারিগুলির ফ্যাক্টর দ্বারা 5000 কলাম দ্বারা বাড়ানো হয়, সময়টি কেবল 0.09 সেকেন্ডে চলে যায় - কেবল 3 বা এর একটি উপাদান - এই অ্যালগরিদমের স্কেলিবিলিটি প্রদর্শন করে) কেবল 0, 1 এবং 2 এর গ্রিড আউটপুট করে, এটি নতুন কক্ষগুলি বরাদ্দ করা হয়েছিল এমন ক্রমটি আউটপুট করে। চিত্রটিতে প্রাথমিকতম কোষগুলি সবুজ, সোনার মাধ্যমে স্যামন রঙগুলিতে স্নাতক।
এটা স্পষ্ট হওয়া উচিত যে প্রতিটি কক্ষের একটি আট-পয়েন্ট পাড়া ব্যবহার করা হচ্ছে। অন্যান্য পাড়াগুলির জন্য কেবল nbrhood
শুরুর কাছাকাছি মানটি সংশোধন করুন expand
: এটি কোনও প্রদত্ত ঘরের তুলনায় সূচক অফসেটের তালিকা of উদাহরণস্বরূপ, "D4" পাড়া হিসাবে নির্দিষ্ট করা যেতে পারে matrix(c(-1,0, 1,0, 0,-1, 0,1), nrow=2)
।
এটি স্পষ্টও যে স্প্রেডের এই পদ্ধতির সমস্যা রয়েছে: এটি পিছনে গর্ত ফেলে। যদি তা না হয় তবে এই সমস্যাটি সমাধানের বিভিন্ন উপায় রয়েছে। উদাহরণস্বরূপ, উপলভ্য কক্ষগুলিকে একটি সারিতে রাখুন যাতে পাওয়া প্রাচীনতম কক্ষগুলিও পূর্ণতম পূরণ করা হয়। কিছু র্যান্ডমাইজেশন এখনও প্রয়োগ করা যেতে পারে, তবে উপলব্ধ কক্ষগুলি আর অভিন্ন (সমান) সম্ভাবনার সাথে বেছে নেওয়া হবে না। আর একটি, আরও জটিল উপায় হ'ল সম্ভাব্যতার সাথে উপলব্ধ কক্ষগুলি নির্বাচন করা যা তাদের কতটা ভরা প্রতিবেশীর উপর নির্ভর করে। একবার কোনও ঘরের চারপাশে পরিণত হওয়ার পরে, আপনি এর নির্বাচনের সুযোগটি এত বেশি করে তুলতে পারেন যে কয়েকটি ছিদ্র পূরণ না করে।
আমি মন্তব্য করে শেষ করব যে এটি কোনও সেলুলার অটোমেটন (সিএ) নয়, যা সেল দ্বারা কোষটি এগিয়ে যায় না, পরিবর্তে প্রতিটি প্রজন্মের কোষগুলির পুরো সোয়েট আপডেট করবে। পার্থক্যটি সূক্ষ্ম: সিএ সহ, কোষগুলির জন্য নির্বাচনের সম্ভাবনাগুলি অভিন্ন হবে না।
#
# Expand a patch randomly within indicator array `x` (1=unoccupied) by
# `n.size` cells beginning at index `start`.
#
expand <- function(x, n.size, start) {
if (x[start] != 1) stop("Attempting to begin on an unoccupied cell")
n.rows <- dim(x)[1]
n.cols <- dim(x)[2]
nbrhood <- matrix(c(-1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1), nrow=2)
#
# Adjoin one more random cell and update `state`, which records
# (1) the immediately available cells and (2) already occupied cells.
#
grow <- function(state) {
#
# Find all available neighbors that lie within the extent of `x` and
# are unoccupied.
#
neighbors <- function(i) {
n <- c((i-1)%%n.rows+1, floor((i-1)/n.rows+1)) + nbrhood
n <- n[, n[1,] >= 1 & n[2,] >= 1 & n[1,] <= n.rows & n[2,] <= n.cols,
drop=FALSE] # Remain inside the extent of `x`.
n <- n[1,] + (n[2,]-1)*n.rows # Convert to *vector* indexes into `x`.
n <- n[x[n]==1] # Stick to valid cells in `x`.
n <- setdiff(n, state$occupied)# Remove any occupied cells.
return (n)
}
#
# Select one available cell uniformly at random.
# Return an updated state.
#
j <- ceiling(runif(1) * length(state$available))
i <- state$available[j]
return(list(index=i,
available = union(state$available[-j], neighbors(i)),
occupied = c(state$occupied, i)))
}
#
# Initialize the state.
# (If `start` is missing, choose a value at random.)
#
if(missing(start)) {
indexes <- 1:(n.rows * n.cols)
indexes <- indexes[x[indexes]==1]
start <- sample(indexes, 1)
}
if(length(start)==2) start <- start[1] + (start[2]-1)*n.rows
state <- list(available=start, occupied=c())
#
# Grow for as long as possible and as long as needed.
#
i <- 1
indices <- c(NA, n.size)
while(length(state$available) > 0 && i <= n.size) {
state <- grow(state)
indices[i] <- state$index
i <- i+1
}
#
# Return a grid of generation numbers from 1, 2, ... through n.size.
#
indices <- indices[!is.na(indices)]
y <- matrix(NA, n.rows, n.cols)
y[indices] <- 1:length(indices)
return(y)
}
#
# Create an interesting grid `x`.
#
n.rows <- 3000
n.cols <- 5000
x <- matrix(1, n.rows, n.cols)
ij <- sapply(1:n.cols, function(i)
c(ceiling(n.rows * 0.5 * (1 + exp(-0.5*i/n.cols) * sin(8*i/n.cols))), i))
x[t(ij)] <- 0; x[t(ij - c(1,0))] <- 0; x[t(ij + c(1,0))] <- 0
#
# Expand around a specified location in a random but reproducible way.
#
set.seed(17)
system.time(y <- expand(x, 250, matrix(c(5, 21), 1)))
#
# Plot `y` over `x`.
#
library(raster)
plot(raster(x[n.rows:1,], xmx=n.cols, ymx=n.rows), col=c("#2020a0", "#f0f0f0"))
plot(raster(y[n.rows:1,] , xmx=n.cols, ymx=n.rows),
col=terrain.colors(255), alpha=.8, add=TRUE)
সামান্য পরিবর্তন সহ আমরা expand
একাধিক ক্লাস্টার তৈরি করতে লুপ করতে পারি । এটি সনাক্তকারী দ্বারা ক্লাস্টারগুলিকে আলাদা করার পরামর্শ দেওয়া হচ্ছে, যা এখানে 2, 3, ... ইত্যাদি চলবে
প্রথমে, ত্রুটি থাকলে প্রথম লাইনে expand
(ক) ফিরে আসার পরিবর্তন করুন NA
এবং (খ) indices
ম্যাট্রিক্সের পরিবর্তে মানগুলি y
। ( y
প্রতিটি কলের সাথে একটি নতুন ম্যাট্রিক্স তৈরি করতে সময় নষ্ট করবেন না )) এই পরিবর্তনটি করা, লুপ করা সহজ: একটি এলোমেলো শুরু চয়ন করুন, এর চারপাশে প্রসারিত করার চেষ্টা করুন, indices
সফল হলে ক্লাস্টার সূচকগুলি সংগ্রহ করুন এবং শেষ না হওয়া পর্যন্ত পুনরাবৃত্তি করুন। লুপের মূল অংশটি হ'ল বহুসংখ্যক ক্লাস্টার সন্ধান না করা হলে পুনরাবৃত্তির সংখ্যা সীমাবদ্ধ করা: এটি দিয়ে সম্পন্ন করা হয়েছে count.max
।
এখানে একটি উদাহরণ যেখানে 60 ক্লাস্টার কেন্দ্রগুলি এলোমেলোভাবে একত্রে নির্বাচিত হয়।
size.clusters <- 250
n.clusters <- 60
count.max <- 200
set.seed(17)
system.time({
n <- n.rows * n.cols
cells.left <- 1:n
cells.left[x!=1] <- -1 # Indicates occupancy of cells
i <- 0
indices <- c()
ids <- c()
while(i < n.clusters && length(cells.left) >= size.clusters && count.max > 0) {
count.max <- count.max-1
xy <- sample(cells.left[cells.left > 0], 1)
cluster <- expand(x, size.clusters, xy)
if (!is.na(cluster[1]) && length(cluster)==size.clusters) {
i <- i+1
ids <- c(ids, rep(i, size.clusters))
indices <- c(indices, cluster)
cells.left[indices] <- -1
}
}
y <- matrix(NA, n.rows, n.cols)
y[indices] <- ids
})
cat(paste(i, "cluster(s) created.", sep=" "))
310 বাই 500 গ্রিডে প্রয়োগ করার সময় এখানে ফলাফল রয়েছে (ক্লাস্টারগুলি সুস্পষ্ট হওয়ার জন্য যথেষ্ট ছোট এবং মোটা করা)। এটি কার্যকর করতে দুই সেকেন্ড সময় লাগে; 3100 বাই 5000 গ্রিডে (100 গুণ বড়) এটি বেশি সময় নেয় (24 সেকেন্ড) তবে সময়টি যথাযথভাবে স্কেলিং করছে। (অন্যান্য প্ল্যাটফর্মগুলিতে, যেমন সি ++ তে সময় নির্ধারণ করা গ্রিড আকারের উপর নির্ভর করে না))