选择一组对以便最小化组的rms

时间:2013-06-17 15:46:35

标签: algorithm rms minimization

简化问题

我有~40个电阻(所有相同的值+ -5%),我需要选择其中的12个,以便它们尽可能相似。

解决方案:我按顺序列出它们,并以最小的RMS连续12次。

实际问题

我有~40个电阻(所有相同的值+ -5%),我必须选择12个,以便对的电阻尽可能相似。

备注

该对(R1,R2)的电阻为R1 + R2。 我并不真正关心编程语言,但是我想说我正在寻找一种C ++或Python的解决方案,这是我最熟悉的两种语言。

4 个答案:

答案 0 :(得分:1)

这给出了相当不错的结果(在MATLAB中)

a = ones(40,1) + rand(40,1)*0.1-0.05; % The resistors
vec = zeros(40,2);        % Initialize matrix
indices = zeros(40,2);    % Initialize matrix
a = sort(a);              % Sort vector of resistors
for ii = 1:length(a)
  vec(ii,:) = [a(ii) a(ii)];    % Assign resistor values to row ii of vec
  indices(ii,:) = [ii,ii];      % Corresponding resistor number (index)
  for jj = 1:length(a)
    if sum(abs((a(ii)+a(jj))-2*mean(a))) < abs(sum(vec(ii,:))-2*mean(a))
      vec(ii,:) =  [a(ii) a(jj)];    % Check if the new set is better than the
      indices(ii,:) = [ii, jj];      % previous, and update vec and indices if true.
    end
  end
end

[x, idx] = sort(sum(vec')');   % Sort the sum of the pairs 
final_list = indices(idx);     % The indices of the sorted pairs

这是我绘制时的结果:

enter image description here

答案 1 :(得分:1)

这不是最佳的,但应该给出一些不错的结果。如果您需要从10000个电阻器中选择1000对,那么速度非常快......

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>

#define GROUPS 12
#define N 40

int compare (const void * a, const void * b)
{
  return ( *(int*)a - *(int*)b );
}

int main ()
{
    // generate random numbers 
    float *values = (float *)malloc(sizeof(float) * N);
    srand(time(0));
    for (int i = 0; i < N; i++)
        values[i] = 950 + rand()%101;

    qsort(values, N, sizeof(float), compare);

    // find "best" pairing
    float bestrms = -1;
    int beststart = -1;
    float bestmean = -1;
    for (int start = 0; start <= N - 2 * GROUPS; start++)
    {
        float sum = 0;
        for (int i = start; i < start + 2 * GROUPS; i++)
            sum += values[i];

        float mean = sum / GROUPS;

        float square = 0;
        for (int i = 0; i < GROUPS; i++)
        {
            int x = start + 2 * GROUPS - 1 - i;
            float first = values[start + i];
            // in a sorted sequence of 24 resistors, always pair 1st with 24th, 2nd with 23rd, etc
            float second = values[start + 2 * GROUPS - 1 - i];
            float err = mean - (first + second);
            square += err * err;
        }

        float rms = sqrt(square/GROUPS);       

        if (bestrms == -1 || rms < bestrms)
        {
            bestrms = rms;
            beststart = start;
            bestmean = mean;
        }
    }

    for (int i = 0; i < GROUPS; i++)
    {             
        float first = values[beststart + i];
        float second = values[beststart + 2 * GROUPS - 1 - i];
        float err = bestmean - (first + second);
        printf("(%f, %f) %f %f\n", first, second, first + second, err);
    }
    printf("mean %f rms %f\n", bestmean, bestrms);
    free(values);
}

答案 2 :(得分:0)

对它们进行排序,然后将1与2,3配对,4与5配对,依此类推。找出每对之间的差异并再次排序,选择差异最小的12。

答案 3 :(得分:0)

  1. 按阻力排序
  2. 配对1与40,2与39等,计算每对的R1 + R2并选择最佳的12对(需要另一个排序步骤)。计算所有选择的平均值(R1 + R2)。
  3. 试图通过尝试为剩下的16个电阻中的一个插入所选择的24个电阻中的一个来连续改进这个初始解决方案。如果新对的组合阻力比旧对的组合阻力更接近平均值,则尝试将成功。重复此步骤,直到找不到任何进一步的改进。
  4. 这个解决方案肯定不会总是计算出最佳解决方案,但它可能已经足够好了。另一个想法是模拟退火,但这将是更多的工作,仍然不能保证找到最佳解决方案。