4

Simplified problem

I have ~40 resistors (all the same value +-5%) and I need to select 12 of them so that they are as similar as possible.

Solution: I list them in order and take the 12 consecutive with the smallest RMS.

The actual problem

I have ~40 resistors (all the same value +-5%) and I have to choose 12 pairs of them so that the resistance of the pairs is as similar as possible.

Notes

The resistance of the pair (R1,R2) is R1+R2. I do not really care about the programming language, but let's say that I'm looking for a solution in C++ or Python, the two languages I'm most familiar with.

4

4 回答 4

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);
}
于 2013-06-17T19:26:58.263 回答
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

这是我绘制它时的结果:

在此处输入图像描述

于 2013-06-17T16:38:29.973 回答
0
  1. 按阻力排序
  2. 对 1 和 40、2 和 39 等,计算每对的 R1+R2 并选择 12 对的最佳集合(需要另一个排序步骤)。计算所有选择的平均值 (R1+R2)。
  3. 通过尝试将剩余 16 个电阻器中的一个插入 24 个选定电阻器中的一个,尝试依次改进这个初始解决方案。如果新货币对的综合阻力比旧货币对的综合阻力更接近均值,则尝试会成功。重复此步骤,直到找不到任何进一步的改进。

这个解决方案肯定不会总是计算出最佳解决方案,但它可能已经足够好了。另一个想法是模拟退火,但这将是更多的工作,并且仍然不能保证找到最佳解决方案。

于 2013-06-17T17:04:21.763 回答
0

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

于 2013-06-17T16:31:11.350 回答