I have a few questions about setting up NLopt with non-linear constraints:
If the number of constraints is bigger than the number of variables, how can we set grad[ ] in the constraint function? Is there any (automatic) method to solve the problem without introducing Lagrangian multiplier?
Using a Lagrangian multiplexer, I know we can solve the problem. However the use of Lagrangian multiplexer we have to obtain my_constraint_data manually, which make it difficult to solve large-scale problem.
For example, suppose I want to minimize the function
f(x1,x2) = -((x1)^3)-(2*(x2)^2)+(10*(x1))-6-(2*(x2)^3)
subject to the following constraints:
Constraint 1: c1 = 10-(x1)*(x2) >= 0
Constraint 2: c2 = ((x1)*(x2)^2)-5 >= 0
Constraint 3: c3 = (x2)-(x1)*(x2)^3 >= 0
In NLopt tutorial, we know that grad[0] = d(c1)/d(x1) and grad[1] = d(c2)/d(x2) as the gradient of constraints. Then, we set grad as follows:
double myconstraint(unsigned n, const double *x, double *grad, void *data) {
my_constraint_data *d = (my_constraint_data *)data;
if (grad) {
grad[0] = -x[1]; //grad[0] = d(c1)/dx[1]
grad[1] = 2*x[0]+x[1]; //grad[1] = d(c2)/dx[2]
grad[2] = ???; //grad[2] = d(c3)/dx[3] but we only have 2 variable (x1)&(x2)
}
return (10-x[0]*x[1], x[0]*x[1]*x[1]-5, x[1]-x[0]*x[1]*x[1]*x[1];
}
The problem is we do not know how to set grad[ ] (especially for c3) if the number of constraints are larger than the number of variables.
Of course we can solve the problem with non-automatic method like below by using Lagrangian multiplexer (l1, l2, l3) where
grad[0] = -l1*(d(c1)/d(x1))-l2*(d(c2)/d(x1))-l3*(d(c)/d(x1))
and
grad[1] = -l1*(d(c1)/d(x2))-l2*(d(c2)/d(x2))-l3*(d(c)/d(x3))
double myconstraint(unsigned n, const double *x, double *grad, void *data) {
my_constraint_data *d = (my_constraint_data *)data;
//set l1, l2, and l3 as parameter of lagrangian multiplier
double l1=d->l1,l2=d->l2,l3=d->l3;
++count;
if (grad) {
grad[0] = l1*x[1]-l2*x[1]*x[1]-l3*x[1]*x[1]*x[1];
grad[1] = l1*x[0]-2*l2*x[0]*x[1]-l3+3*l3*x[0]*x[1]*x[1];
}
return (10-x[0]*x[1], x[0]*x[1]*x[1]-5, x[1]-x[0]*x[1]*x[1]*x[1]);
}
Meanwhile, it is not easy to apply non-automatic method into large-scale problem because it will be inefficient and complicated in programming.
Is there any method to solve nonlinear simultaneous equations using NLopt? (When Lagrangian multiplexer is applied in case of the number of constraints are larger than the number of variables, nonlinear simultaneous equations should be solved.).
We appreciate for your answer. It will be really helpful to us. Thank you for all your kindness.
I think you've got the constraints and the variables you are minimizing mixed up. If I understand your question correctly, you need to create three separate constraint functions for your three constraints. For example:
double c1(unsigned n, const double *x, double *grad, void *data)
{
/* Enforces the constraint
*
* 10 - x1*x2 >= 0
*
* Note we compute x1*x2 - 10 instead of 10 - x1*x2 since nlopt expects
* inequality constraints to be of the form h(x) <= 0. */
if (grad) {
grad[0] = x[1]; // grad[0] = d(c1)/dx1
grad[1] = x[0]; // grad[1] = d(c1)/dx2
}
return x[0]*x[1] - 10;
}
double c2(unsigned n, const double *x, double *grad, void *data)
{
/* Enforces the constraint
*
* x1*x2^2 - 5 >= 0
*
* Note we compute -x1*x2^2 - 5 instead of x1*x2^2 - 5 since nlopt expects
* inequality constraints to be of the form h(x) <= 0. */
if (grad) {
grad[0] = -x[1]*x[1];
grad[1] = -2*x[0]*x[1];
}
return -x[0]*x[1]*x[1] + 5;
}
Then, in your main function you need to add each inequality constraint separately:
int main(int argc, char **argv)
{
// set up nlopt here
/* Add our constraints. */
nlopt_add_inequality_constraint(opt, c1, NULL, 1e-8);
nlopt_add_inequality_constraint(opt, c2, NULL, 1e-8);
// etc.
}
Here is Mu-Law encoder taken from NAudio. The question is how is this formula same with the code? I can understand that MuLawCompressTable is actually the Log but I dont get the thing about mantissa why it is taken as is.
private const int cBias = 0x84;
private const int cClip = 32635;
private static readonly byte[] MuLawCompressTable = new byte[256]
{
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
public static byte LinearToMuLawSample(short sample)
{
//We get the sign
int sign = (sample >> 8) & 0x80;
if (sign != 0)
sample = (short)-sample;
if (sample > cClip)
sample = cClip;
sample = (short)(sample + cBias);
int exponent = (int)MuLawCompressTable[(sample >> 7) & 0xFF];
int mantissa = (sample >> (exponent + 3)) & 0x0F;
int compressedByte = ~(sign | (exponent << 4) | mantissa);
return (byte)compressedByte;
}
They are different. See the Wikipedia page on mu-law, http://en.wikipedia.org/wiki/Mulaw
There are two forms of this algorithm—an analog version, and a quantized digital version.
You quote the formula for the "analog" version - a compressive mapping from -1..1 to -1..1, which emphasizes the basic idea of mu-law, i.e. that the quantized value encodes more detail (uses a smaller quantization step) for smaller values, so the introduced quantization error is roughly proportional to the overall amplitude of the signal.
The "digital" version is a piecewise-linear approximation to this basic idea, with some additional shifts to further simplify processing.
Here's a plot comparing the two. You can see the stairsteps in the green line (mu_digital) corresponding to the discrete 7-bit values, and you also spot the different linear sections approximating the smooth blue line.
If you are given red, green, and blue values that range from 0-255, what would be the fastest computation to get just the hue value? This formula will be used on every pixel of a 640x480 image at 30fps (9.2 million times a second) so every little bit of speed optimization helps.
I've seen other formulas but I'm not happy with how many steps they involve. I'm looking for an actual formula, not a built in library function.
Convert the RGB values to the range 0-1, this can be done by dividing the value by 255 for 8-bit color depth (r,g,b - are given values):
R = r / 255 = 0.09
G = g / 255 = 0.38
B = b / 255 = 0.46
Find the minimum and maximum values of R, G and B.
Depending on what RGB color channel is the max value. The three different formulas are:
If Red is max, then Hue = (G-B)/(max-min)
If Green is max, then Hue = 2.0 + (B-R)/(max-min)
If Blue is max, then Hue = 4.0 + (R-G)/(max-min)
The Hue value you get needs to be multiplied by 60 to convert it to degrees on the color circle. If Hue becomes negative you need to add 360 to, because a circle has 360 degrees.
Here is the full article.
In addition to Umriyaev's answer:
If only the hue is needed, it is not required to divide the 0-255 ranged colours with 255.
The result of e.x. (green - blue) / (max - min) will be the same for any range (as long as the colours are in the same range of course).
Here is the java example to get the Hue:
public int getHue(int red, int green, int blue) {
float min = Math.min(Math.min(red, green), blue);
float max = Math.max(Math.max(red, green), blue);
if (min == max) {
return 0;
}
float hue = 0f;
if (max == red) {
hue = (green - blue) / (max - min);
} else if (max == green) {
hue = 2f + (blue - red) / (max - min);
} else {
hue = 4f + (red - green) / (max - min);
}
hue = hue * 60;
if (hue < 0) hue = hue + 360;
return Math.round(hue);
}
Edit: added check if min and max are the same, since the rest of the calculation is not needed in this case, and to avoid division by 0 (see comments)
Edit: fixed java error
Probably not the fastest but this is a JavaScript function that you can try directly in the browser by clicking the "Run code snippet" button below
function rgbToHue(r, g, b) {
// convert rgb values to the range of 0-1
var h;
r /= 255, g /= 255, b /= 255;
// find min and max values out of r,g,b components
var max = Math.max(r, g, b), min = Math.min(r, g, b);
// all greyscale colors have hue of 0deg
if(max-min == 0){
return 0;
}
if(max == r){
// if red is the predominent color
h = (g-b)/(max-min);
}
else if(max == g){
// if green is the predominent color
h = 2 +(b-r)/(max-min);
}
else if(max == b){
// if blue is the predominent color
h = 4 + (r-g)/(max-min);
}
h = h*60; // find the sector of 60 degrees to which the color belongs
// https://www.pathofexile.com/forum/view-thread/1246208/page/45 - hsl color wheel
// make sure h is a positive angle on the color wheel between 0 and 360
h %= 360;
if(h < 0){
h += 360;
}
return Math.round(h);
}
let gethue = document.getElementById('gethue');
let r = document.getElementById('r');
let g = document.getElementById('g');
let b = document.getElementById('b');
r.value = Math.floor(Math.random() * 256);
g.value = Math.floor(Math.random() * 256);
b.value = Math.floor(Math.random() * 256);
gethue.addEventListener('click', function(event) {
let R = parseInt(r.value)
let G = parseInt(g.value)
let B = parseInt(b.value)
let hue = rgbToHue(R, G, B)
console.log(`Hue(${R}, ${G}, ${B}) = ${hue}`);
});
<table>
<tr><td>R = </td><td><input id="r"></td></tr>
<tr><td>G = </td><td><input id="g"></td></tr>
<tr><td>B = </td><td><input id="b"></td></tr>
<tr><td colspan="2"><input id="gethue" type="button" value="Get Hue"></td></tr>
</table>
The web page Math behind colorspace conversions, RGB-HSL covers this however it contains what I believe is an error. It states for hue calculation to divide by max-min however if you divide by this fractional amount the value increases and easily exceeds the full expected range of -1 to 5. I found multiplying by max-min to work as expected.
Instead of this:
If Red is max, then Hue = (G-B)/(max-min)
If Green is max, then Hue = 2.0 + (B-R)/(max-min)
If Blue is max, then Hue = 4.0 + (R-G)/(max-min)
I suggest this:
If Red is max, then Hue = (G-B)*(max-min)
If Green is max, then Hue = 2.0 + (B-R)*(max-min)
If Blue is max, then Hue = 4.0 + (R-G)*(max-min)
You must specify which language and platform you're using because C#, Java and C are very different languages and the performance also varies among them and among the platforms. The question is currently too broad!!!
640×480 is not very large compared to current common resolutions, but "fastest" is subjective and you need to do careful benchmarking to choose which is best for your usecase. An algorithm that looks longer with many more steps isn't necessarily slower than a shorter one because instruction cycles are not fixed and there are many other factors that affect performance such as cache coherency and branch (mis)predictions.
For the algorithm Umriyaev mentioned above, you can replace the division by 255 with a multiplication by 1.0/255, that'll improve performance with a tiny acceptable error.
But the best way will involve vectorization and parallelization in some way because modern CPUs have multiple cores and also SIMD units to accelerate math and multimedia operations like this. For example x86 has SSE/AVX/AVX-512... which can do things on 8/16/32 channels at once. Combining with multithreading, hardware acceleration, GPU compute.... it'll be far better than any answers in this question.
In C# and Java there weren't many vectorization options in the past so with older .NET and JVM versions you need to run unsafe code in C#. In Java you can run native code through JNI. But nowadays all of them also had vectorized math support. Java had a new Vector API in JEP-338. In Mono you can use the vector type in the Mono.Simd namespace. In RyuJIT there's Microsoft.Bcl.Simd. In .NET 1.6+ there's System.Numerics which includes Vector and other
... SIMD-enabled vector types, which include Vector2, Vector3, Vector4, Matrix3x2, Matrix4x4, Plane, and Quaternion.
How to use the Intel AVX in Java?
Parallelism on a Single Core - SIMD with C#
SIMD in Depth - Performance and Cost in C# and C++
Will .NET ever do intelligent SIMD?
Using System.Numerics.Vector for Graphics Programming
System.Numerics.Vectors 'Vector<T>': is it basically just System.UInt128?
Performance Gains with Data Parallelism: Using SIMD Instructions from C#
You could use one of the mathematical techniques suggested here, but instead of doing it on every pixel, do it on a random sample of ~10% of the pixels. This is still very likely to have high accuracy and will be 10x as fast.