Path: news.mathworks.com!not-for-mail
From: "Frédéric Bergeron" <frederic.bergeron@logiag.com>
Newsgroups: comp.soft-sys.matlab
Subject: Re: Simple optimisation question
Date: Mon, 28 Jun 2010 16:25:30 +0000 (UTC)
Organization: The MathWorks, Inc.
Lines: 92
Message-ID: <i0aidq$stt$1@fred.mathworks.com>
References: <i0a8gm$kju$1@fred.mathworks.com> <i0ad6n$91i$1@fred.mathworks.com> <i0afpa$3is$1@fred.mathworks.com>
Reply-To: "Frédéric Bergeron" <frederic.bergeron@logiag.com>
NNTP-Posting-Host: webapp-03-blr.mathworks.com
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
X-Trace: fred.mathworks.com 1277742330 29629 172.30.248.38 (28 Jun 2010 16:25:30 GMT)
X-Complaints-To: news@mathworks.com
NNTP-Posting-Date: Mon, 28 Jun 2010 16:25:30 +0000 (UTC)
X-Newsreader: MATLAB Central Newsreader 2372199
Xref: news.mathworks.com comp.soft-sys.matlab:648714

"Matt J " <mattjacREMOVE@THISieee.spam> wrote in message <i0afpa$3is$1@fred.mathworks.com>...
> "Matt J " <mattjacREMOVE@THISieee.spam> wrote in message <i0ad6n$91i$1@fred.mathworks.com>...
> 
> > 
> > I could be wrong, but it seems like you can solve this by simple algebra. Let's make the following definitions
> > 
> > N=length(data); %known 
> > S=sum(data); %known
> > O=sum(data(over)-x)
> > U=sum(x-data(under))
> > 
> > Then you have 2 equations that allow you to solve for O and U:
> > 
> > O-R*U=0
> > O+U=S;
> ========
> 
> Forget it. I pulled the equation O+U=S from my imagination somehow.
> 
> In any case, there are at most N different possibilities for the sets
> data(over) and data(under). For each one, x ranges over a known interval separating data(over) from data(under) and in that interval  O -R*U is a known linear function of x. You could simply loop over each of these N sets and test whether 
> O(x)-R*U(x) has a root in that interval.


Hey thank you,


The O+U=S equation is fine for me, I just don't get the O-U=S-N*x.
Anyway, I decided to do a loop for a lot of values in the interval [min(data) max(data)], than calulate the ratio R for each of them and then take the value associated with the ratio R the closest than the previously defined one.

So I started by making a for loop, than I tought a while loop will be better and more efficient to locate the value with the least error on R. I redefine the upper or lower value of the interval for each while loop, and it's way faster. Here's my code if someone interested:

*****************************
clear all;

%Input
R=2;                %Cut/fill ratio
datamin=55;
datamax=65;
data=datamin+(datamax-datamin)*rand(1,50);

%% First method
tic;
x=min(data):(max(data)-min(data))/200:max(data);
for i=1:length(x)
    y(i)=abs(R*sum(x(i)-data(data<x(i)))-sum(data(data>=x(i))-x(i)));
end
x_best1=x(y==min(y));
R2_1=sum(data(data>=x_best1)-x_best1)/sum(x_best1-data(data<x_best1));
erreur_ratio1=abs(R2_1-R)/R;
t1=toc;

%% Second method
tic;
erreur_ratio2=1;     %error on R
x1=min(data);   %Lower value of the interval around the x_best
x2=max(data);   %Upper value
                    
while erreur_ratio2>0.01

    %Calculs
    x_best2=x1+(x2-x1)/2; %Taking the middle value of the interval

    R2_2=sum(data(data>=x_best2)-x_best2)/sum(x_best2-data(data<x_best2));
    if R2_2==R;
        break   %If the good ratio is found
    elseif R2_2<R
        x2=x_best2;
    else %R2>R
        x1=x_best2;
    end
    erreur_ratio2=abs(R2_2-R)/R;
end
t2=toc;

%% Methods comparison
fprintf('\nt1= %g\nerreur_ratio1= %g\nx_best1= %g\n',t1,erreur_ratio1,x_best1);
fprintf('\nt2= %g\nerreur_ratio2= %g\nx_best2= %g\n\n',t2,erreur_ratio2,x_best2);

****************
and I get:

t1= 0.030075
erreur_ratio1= 0.0113545
x_best1= 59.3732

t2= 0.0003564
erreur_ratio2= 0.00205718
x_best2= 59.3845

Thanks again for the answers!!
Fred