I've developed a few GUI-oriented applications that implement their own text line-breaking algorithms. For example, consider that my applications consist of typical GUI "widgets" that can be laid out on a screen. Widgets such as checkboxes, textfields, simple labels, etc, are fairly easy to draw. However, a widget such as a "paragraph" (an arbitrary amount of multiline text, which should be fit into a specified box, with line-breaking occurring as necessary) is much more difficult owing to the, well, line-breaking part.
Every time I've implemented such an algorithm, I've used an approach that's worked but has been pretty inefficient. My general approach (to fit a string into a box with width w) has been to iteratively take a string s, use font metrics to measure its pixel length l, and whittle away at it until l <= w. Then the remainder is assigned to s, and I repeat the process until I'm left with a value of s that's less than or equal to w.
At the bottom of this is a Javascript example (which admittedly probably isn't the best environment in which to be doing this sort of thing). This code would be part of the aforementioned "paragraph" widget, and is written for the HTML5 Canvas API (ctx is the Canvas' graphics context). Clearly, the Big-O analysis of this approach is pretty poor. But... is there a better way to do this sort of thing? I'm assuming it depends somewhat on the environment in which we're working. But I also assume that given the number of text-editing tools that exist, an efficient solution exists out there.
// the paragraph widgets' main drawing function
this.drawText = function(ctx) {
...
var lines = this.text.split("\n"); // here we account for user-entered line breaks
var y = this.y;
for (var i=0; i<lines.length; i++) {
var currTxt = lines[i]; // a chunk of text in between user-entered line breaks
var miniLines = this.breakToLines(currTxt, this.textWidth(), ctx);
for (var j = 0; j < miniLines.length; j++) {
var miniTxt = miniLines[j];
var x = this.x + ( (this.round) ? this.cornerRadius : 0 );
x += this.textOffset();
y += this.fontSize;
ctx.save();
ctx.rect(this.x, this.y, this.width, this.height);
ctx.clip();
ctx.fillText(miniTxt, x, y);
ctx.restore();
}
};
};
// take a chunk of text and break it into lines that fit within width 'w'
this.breakToLines = function(txt, w, ctx) {
var arr = [];
while (true) {
var txt2 = this.popLine(txt, w, ctx);
if (txt2 == null)
break;
arr.push(txt2);
if (txt.length <= txt2.length)
break;
txt = txt.substring(txt2.length);
}
return arr;
};
this.popLine = function(txt, w, ctx) {
var m = ctx.measureText(txt); // 'm' represents the size of the text
if (m.length == 0)
return null; // 'm' is empty, so we're done
while (m.width > w) {
// remove a word from txt and re-measure it
txt = txt.substring(0, txt.lastIndexOf(' '));
m = ctx.measureText(txt);
}
return txt;
};
I wonder if the text metrics give reliable results when measuring the size of a word followed by a space. For example, does width( "aaa " ) + width( "bbb" ) = width( "aaa bbb" )? If so you can measure each word in the text, with and without a space after it, and figure the rest out from there. Plan B (assuming that text metrics for a word followed by a space doesn't give precise results) is to measure each word without the space, and use a fixed value to estimate the space between words.
The inefficiency in the current algorithm, as I see it, is that you're calling the measureText method O(n^2) times, and you're measuring the width of long strings. By breaking the text into words and measuring each word, you would only call measureText O(n) times, and you would be calling it on relatively short strings.
The proposed algorithm then is to start at the beginning of each line and add words until the wrap limit is reached. This additive approach to the problem reduces the number of strings that must be measured, as well as reducing the length of the strings that must measured.
Related
I'm using GA, so I took example from this page (http://www.ai-junkie.com/ga/intro/gat3.html) and tried to do on my own.
The problem is, it doesn't work. For example, maximum fitness does not always grow in the next generation, but becomes smallest. Also, after some number of generations, it just stops getting better. For example, in first 100 generations, it found the largest circle with radius 104. And in next 900 largest radius is 107. And after drawing it, I see that it can grow much more.
Here is my code connected with GA. I leave out generating random circles, decoding and drawing.
private Genome ChooseParent(Genome[] population, Random r)
{
double sumFitness = 0;
double maxFitness = 0;
for (int i = 0; i < population.Length; i++)
{
sumFitness += population[i].fitness;
if (i == 0 || maxFitness < population[i].fitness)
{
maxFitness = population[i].fitness;
}
}
sumFitness = population.Length * maxFitness - sumFitness;
double randNum = r.NextDouble() *sumFitness;
double acumulatedSum = 0;
for(int i=0;i<population.Length;i++)
{
acumulatedSum += population[i].fitness;
if(randNum<acumulatedSum)
{
return population[i];
}
}
return population[0];
}
private void Crossover(Genome parent1, Genome parent2, Genome child1, Genome child2, Random r)
{
double d=r.NextDouble();
if(d>this.crossoverRate || child1.Equals(child2))
{
for (int i = 0; i < parent1.bitNum; i++)
{
child1.bit[i] = parent1.bit[i];
child2.bit[i] = parent2.bit[i];
}
}
else
{
int cp = r.Next(parent1.bitNum - 1);
for (int i = 0; i < cp; i++)
{
child1.bit[i] = parent1.bit[i];
child2.bit[i] = parent2.bit[i];
}
for (int i = cp; i < parent1.bitNum; i++)
{
child1.bit[i] = parent2.bit[i];
child2.bit[i] = parent1.bit[i];
}
}
}
private void Mutation(Genome child, Random r)
{
for(int i=0;i<child.bitNum;i++)
{
if(r.NextDouble()<=this.mutationRate)
{
child.bit[i] = (byte)(1 - child.bit[i]);
}
}
}
public void Run()
{
for(int generation=0;generation<1000;generation++)
{
CalculateFitness(population);
System.Diagnostics.Debug.WriteLine(maxFitness);
population = population.OrderByDescending(x => x).ToArray();
//ELITIZM
Copy(population[0], newpopulation[0]);
Copy(population[1], newpopulation[1]);
for(int i=1;i<this.populationSize/2;i++)
{
Genome parent1 = ChooseParent(population, r);
Genome parent2 = ChooseParent(population, r);
Genome child1 = newpopulation[2 * i];
Genome child2 = newpopulation[2 * i + 1];
Crossover(parent1, parent2, child1, child2, r);
Mutation(child1, r);
Mutation(child2, r);
}
Genome[] tmp = population;
population = newpopulation;
newpopulation = tmp;
DekodePopulation(population); //decoding and fitness calculation for each member of population
}
}
If someone can point on potential problem that caused such behaviour and ways to fix it, I'll be grateful.
Welcome to the world of genetic algorithms!
I'll go through your issues and suggest a potential problem. Here we go:
maximum fitness does not always grow in the next generation, but becomes smallest - You probably meant smaller. This is weird since you employed elitism, so each generation's best individual should be at least as good as in the previous one. I suggest you check your code for mistakes because this really should not happen. However, the fitness does not need to always grow. It is impossible to achieve this in GA - it's a stochastic algorithm, working with randomness - suppose that, by chance, no mutation nor crossover happens in a generation - then the fitness cannot improve to the next generation since there is no change.
after some number of generations, it just stops getting better. For example, in first 100 generations, it found the largest circle with radius 104. And in next 900 largest radius is 107. And after drawing it, I see that it can grow much more. - this is (probably) a sign of a phenomenon called premature convergence and it's, unfortunately, a "normal" thing in genetic algorithm. Premature convergence is a situation when the whole population converges to a single solution or to a set of solutions which are near each other and which is/are sub-optimal (i.e. it is not the best possible soluion). When this happens, the GA has a very hard time escaping this local optimum. You can try to tweak the parameters, especially the mutation probability, to force more exploration.
Also, another very important thing that can cause problems is the encoding, i.e. how is the bit string mapped to the circle. If the encoding is much too indirect, it can lead to poor performance of the GA. GAs work when there are some building blocks in the genotype which can be exchanged between among the population. If there are no such blocks, the performance of a GA is usually going to be poor.
I have implemented this exercise and achieved good results. Here is the link:
https://github.com/ManhTruongDang/ai-junkie
Hope this can be of use to you.
So normally and very inefficiently min/max filter is implemented by using four for loops.
for( index1 < dy ) { // y loop
for( index2 < dx ) { // x loop
for( index3 < StructuringElement.dy() ) { // kernel y
for( index4 < StructuringElement.dx() ) { // kernel x
pixel = src(index3+index4);
val = (pixel > val) ? pixel : val; // max
}
}
dst(index2, index1) = val;
}
}
However this approach is damn inefficient since it checks again previously checked values. So I am wondering what methods are there to implement this with using previously checked values on next iteration?
Any assumptions regarding structuring element size/point of origin can be made.
Update: I am especially keen to know any insights of this or kind of implementation: http://dl.acm.org/citation.cfm?id=2114689
I have been following this question for some time, hoping someone would write a fleshed-out answer, since I am pondering the same problem.
Here is my own attempt so far; I have not tested this, but I think you can do repeated dilation and erosion with any structuring element, by only accessing each pixel twice:
Assumptions: Assume the structuring element/kernel is a KxL rectangle and the image is a NxM rectangle. Assume that K and L are odd.
The basic approach you outlined has four for loops and takes O(K*L*N*M) time to complete.
Often you want to dilate repeatedly with the same kernel, so the time is again multiplied by the desired number of dilations.
I have three basic ideas for speeding up the dilation:
dilation by a KxL kernel is equal to dilation by a Kx1 kernel followed by dilation by a 1xL kernel. You can do both of these dilations with only three for loops, in O(KNM) and O(LNM)
However you can do a dilation with a Kx1 kernel much faster: You only need to access each pixel once. For this you need a particular data structure, explained below. This allows you to do a single dilation in O(N*M), regardless of the kernel size
repeated dilation by a Kx1 kernel is equal to a single dilation by a larger kernel. If you dilate P times with a Kx1 kernel, this is equal to a single dilation with a ((K-1)*P + 1) x 1 kernel.
So you can do repeated dilation with any kernel size in a single pass, in O(N*M) time.
Now for a detailed description of step 2.
You need a queue with the following properties:
push an element to the back of the queue in constant time.
pop an element from the front of the queue in constant time.
query the current smallest or largest element in the queue in constant time.
How to build such a queue is described in this stackoverflow answer: Implement a queue in which push_rear(), pop_front() and get_min() are all constant time operations.
Unfortunately not much pseudocode, but the basic idea seems sound.
Using such a queue, you can calculate a Kx1 dilation in a single pass:
Assert(StructuringElement.dy()==1);
int kernel_half = (StructuringElement.dx()-1) /2;
for( y < dy ) { // y loop
for( x <= kernel_half ) { // initialize the queue
queue.Push(src(x, y));
}
for( x < dx ) { // x loop
// get the current maximum of all values in the queue
dst(x, y) = queue.GetMaximum();
// remove the first pixel from the queue
if (x > kernel_half)
queue.Pop();
// add the next pixel to the queue
if (x < dx - kernel_half)
queue.Push(src(x + kernel_half, y));
}
}
The only approach I can think of is to buffer the maximum pixel values and the rows in which they are found so that you only have to do the full iteration over a kernel sized row/column when the maximum is no longer under it.
In the following C-like pseudo code, I have assumed signed integers, 2d row-major arrays for the source and destination and a rectangular kernel over [±dx, ±dy].
//initialise the maxima and their row positions
for(x=0; x < nx; ++x)
{
row[x] = -1;
buf[x] = 0;
}
for(sy=0; sy < ny; ++sy)
{
//update the maxima and their row positions
for(x=0; x < nx; ++x)
{
if(row[x] < max(sy-dy, 0))
{
//maximum out of scope, search column
row[x] = max(sy-dy, 0);
buf[x] = src[row[x]][x];
for(y=row[x]+1; y <= min(sy+dy, ny-1); ++y)
{
if(src[y][x]>=buf[x])
{
row[x] = y;
buf[x] = src[y][x];
}
}
}
else
{
//maximum in scope, check latest value
y = min(sy+dy, ny-1);
if(src[y][x] >= buf[x])
{
row[x] = y;
buf[x] = src[y][x];
}
}
}
//initialise maximum column position
col = -1;
for(sx=0; sx < nx; ++sx)
{
//update maximum column position
if(col<max(sx-dx, 0))
{
//maximum out of scope, search buffer
col = max(sx-dx, 0);
for(x=col+1; x <= min(sx+dx, nx-1); ++x)
{
if(buf[x] >= buf[col]) col = x;
}
}
else
{
//maximum in scope, check latest value
x = min(sx+dx, nx-1);
if(buf[x] >= buf[col]) col = x;
}
//assign maximum to destination
dest[sy][sx] = buf[col];
}
}
The worst case performance occurs when the source goes smoothly from a maximum at the top left to a minimum at the bottom right, forcing a full row or column scan at each step (although it's still more efficient than the original nested loops).
I would expect average case performance to be much better though, since regions containing increasing values (both row and column wise) will update the maximum before a scan is required.
That said, not having actually tested it I'd recommend that you run a few benchmarks rather than trust my gut feeling!
a theoretical way of improving the complexity would be to maintain a BST for the KxK pixels, delete previsous Kx1 pixels and add the next Kx1 pixels to it. The cost of this operation would be 2K log K and it would be repeated NxN times. Overall the computation time would become NxNxKxlog K from NxNxKxK
Same kind of optimizations can be used as "non maximum suppression" algorithms
http://www.vision.ee.ethz.ch/publications/papers/proceedings/eth_biwi_00446.pdf
In 1D, using morphological wavelet transform in O(N) :
https://gist.github.com/matovitch/11206318
You could get O(N * M) in 2D. HugoRune solution is way simpler and probably faster (though this one could probably be improved).
There are lots of questions discussing the fastest/best way to rotate a string or determine if one string is a rotation of another.
For example, neglecting sanitization of inputs, you'll see something like this for IsRotation:
public static bool IsRotation(string s1, string s2)
{
return (s1.Length == s2.Length && (s1 + s1).IndexOf(s2) != -1);
}
And something like this for Rotate:
public static string Rotate(string s, int index)
{
//Can't rotate. Return input.
if (s.Length < 2)
{
return s;
}
// Break input in half at rotation index
var s1 = s.Substring(0, index);
var s2 = s.Substring(index);
// Reverse the halves
var s1Reversed = Reverse(s1);
var s2Reversed = Reverse(s2);
// Join the reversed halves
var joined = s1Reversed + s2Reversed;
//Reverse and return the result.
var rotated = Reverse(joined);
return rotated;
}
For example, using "foo..."
Rotate("foo",1) == "ofo"
-and-
IsRotation("foo", "ofo") == true;
My question is is an extension of these questions.
Given an input string, s, determine how many rotations of that string are identical to the original string.
Considering the input string as a rotation, some sample input/output pairs:
IdenticalRotationCount("") == 1
IdenticalRotationCount("s") == 1
IdenticalRotationCount("sa") == 1
IdenticalRotationCount("ss") == 2
IdenticalRotationCount("ByeBye") == 2
IdenticalRotationCount("StackOverflow") == 0
I was told that there is a solution that will run in O(n) time. The beginner solution looks like this:
public static int IdenticalRotationCount(this string s)
{
//If length of s is less than two, we cannot rotate. Return 1.
if (s.Length < 2)
{
return 1;
}
//Get first char in s
var first = s[0];
//Consider input as first rotation that matches
var count = 1;
//Try each rotate position
for (var i = 1; i < s.Length; ++i)
{
var c = s[i];
//If current character doesn't start with same character as input
//we can skip the rotation
if (c != first)
{
continue;
}
//If the rotation at index i equals the input string, add 1 to result
if (StringExtensions.Rotate(s, i) == s)
{
++count;
}
}
return count;
}
However, if you choose an absurd input, like 200,000 consecutive 'a's, it will run for quite some time.
Can anybody provide a solution that runs in O(n) time? I can see N^2 by doing the actual comparison when breaking the input down into the two halves before rotation, instead of doing the actual rotation, but cannot see how to do O(n).
Thanks!
PS - If there is a more appropriate to post this sort of question, please say so in the comments. I'll gladly move it.
This sprung to mind - think about the question "if I concatenate the original string with itself, what's the first index of the original string within the concatenated result". With a little thought, it looks to me as though it'll answer the question O(n).
E.g.
Original string "ByeBye"
Concatenated string "ByeByeByeBye"
Original string appears at (0-based) index 2 within the concatenated string. This tells you something.
If a string is equal to a rotation of itself at offset k and at no smaller offset, then the string must be the repetition of its length k prefix. It will then also be equal to its rotation at all multiples of k, so there will be precisely n/k such rotations, where n is the length of the string. This is pretty easy to prove.
There is indeed an O(n) algorithm for determining the value of k. One way to do it is to use Duval's algorithm for Lyndon factorization (see Wikipedia). That's just a hint; I'll see if I can produce some actual pseudocode if desired.
Right, so let's say I want to compare two BitmapDatas. One is an image of a background (not solid, it has varying pixels), and another is of something (like a sprite) on top of the exact same background. Now what I want to do is remove the background from the second image, by comparing the two images, and removing all the pixels from the background that are present in the second image.
For clarity, basically I want to do this in AS3.
Now I came up with two ways to do this, and they both work perfectly. One compares pixels directly, while the other uses the BitmapData.compare() method first, then copies the appropriate pixels into the result. What I want to know is which way is faster.
Here are my two ways of doing it:
Method 1
for (var j:int = 0; j < layer1.height; j++)
{
for (var i:int = 0; i < layer1.width; i++)
{
if (layer1.getPixel32(i, j) != layer2.getPixel32(i, j))
{
result.setPixel32(i, j, layer2.getPixel32(i, j));
}
}
}
Method 2
result = layer1.compare(layer2) as BitmapData;
for (var j:int = 0; j < layer1.height; j++)
{
for (var i:int = 0; i < layer1.width; i++)
{
if (result.getPixel32(i, j) != 0x00000000)
{
result.setPixel32(i, j, layer2.getPixel32(i, j));
}
}
}
layer1 is the background, layer2 is the image the background will be removed from, and result is just a BitmapData that the result will come out on.
These are very similar, and personally I haven't noticed any difference in speed, but I was just wondering if anybody knows which would be faster. I'll probably use Method 1 either way, since BitmapData.compare() doesn't compare pixel alpha unless the colours are identical, but I still thought it wouldn't hurt to ask.
This might not be 100% applicable to your situation, but FWIW I did some research into this a while back, here's what I wrote back then:
I've been meaning to try out grant skinners performance test thing for a while, so this was my opportunity.
I tested the native compare, the iterative compare, a reverse iterative compare (because i know they're a bit faster) and finally a compare using blendmode DIFFERENCE.
The reverse iterative compare looks like this:
for (var bx:int = _base.width - 1; bx >= 0; --bx) {
for (var by:int = _base.height - 1; by >= 0; --by) {
if (_base.getPixel32(bx, by) != compareTo.getPixel32(bx, by)) {
return false;
}
}
}
return true;
The blendmode compare looks like this:
var test:BitmapData = _base.clone();
test.draw(compareTo, null, null, BlendMode.DIFFERENCE);
var rect:Rectangle = test.getColorBoundsRect(0xffffff, 0x000000, false);
return (rect.toString() != _base.rect.toString());
I'm not 100% sure this is completely reliable, but it seemed to work.
I ran each test for 50 iterations on 500x500 images.
Unfortunately my pixel bender toolkit is borked, so I couldn't try that method.
Each test was run in both the debug and release players for comparison, notice the massive differences!
Complete code is here: http://webbfarbror.se/dump/bitmapdata-compare.zip
You might try a shader that would check if two images are matching, and if not, save one of image's point as output. Like this:
kernel NewFilter
< namespace : "Your Namespace";
vendor : "Your Vendor";
version : 1;
description : "your description";
>
{
input image4 srcOne;
input image4 srcTwo;
output pixel4 dst;
void evaluatePixel()
{
float2 positionHere = outCoord();
pixel4 fromOne = sampleNearest(srcOne, positionHere);
pixel4 fromTwo = sampleNearest(srcTwo, positionHere);
float4 difference=fromOne-fromTwo;
if (abs(difference.r)<0.01&&abs(difference.g)<0.01&&abs(difference.b)<0.01) dst=pixel4(0,0,0,1);
else dst = fromOne;
}
}
This will return black pixel if matched and first image's pixel when no match. Use Pixel Bender to make it run in Flash. Some tutorial is here. Shaders are usually a factor faster than plain AS3 code.
In a program I'm writing in an unnamed language, I have a block of text for which the width is unknown, and all I know is the maximum width that this block of text could be. Given this information, I need to find out the smallest possible width that this text could be (assume that I can't use the metrics of the characters / glyphs or the character count). So far I just have a brute force solution which looks like follows:
for (int i = .1; i < maxTextWidth; i += .1)
{
if (textFitsInGivenWidth(text, i))
{
textWidth = i;
break;
}
}
I'd like to try and optimize this as much as I can. My first thought was to use a binary search, but I'm having trouble implementing this in the proper way (and am not sure if it's even possible). Does anyone have any suggestions on what I could do here to improve the run time using only what I've given in the above solution?
Binary Search is the answer indeed.
http://en.wikipedia.org/wiki/Binary_search_algorithm
for integer binary search, it can be:
minW=0, maxW=maxTextWidth
while(minW<=maxW){
mid=(minW+maxW)/2;
if (textFitsInGivenWidth(text, mid)){
maxW=mid-1;
}else{
minW=mid+1;
}
}
textWidth=minW
The idea is, if you have textFitsInGivenWidth(text, mid) == True,
then you must have textFitsInGivenWidth(text, i) == True for all i>=mid,
and if it's False, then you have textFitsInGivenWidth(text, i) == False for all i<=mid
so each time we check the middle of the interval to be checked, and reduce the interval into half . The time is O(logN), in which N=maxTextWidth
update: for float support, see the example below :
float minW=0, maxW=maxTextWidth
while(1){
if (maxW-minW<0.05)
break;
float mid=(minW+maxW)/2;
if (textFitsInGivenWidth(text, mid)){
maxW=mid;
}else{
minW=mid;
}
}
textWidth=minW
and to get a precision of .1, simply change the last line to :
textWidth=int(minW*10)/10.0