1

I'm porting a C++ algorithm to Python. All has gone well so far (it translated pretty much verbatim, or as least as nearly as a c++ to Python translation could hope to be), all I have left to do is this piece:

int N=6;
Approximate ax,ay;
double e,dt[n];

for (ax.init( 0.0,512.0, 32.0        ,N,   &e);!ax.done;ax.step())
    for (ay.init(  0.0,512.0, 32.0       ,N,   &e);!ay.done;ay.step())
    {
        for (i=0;i<n;i++){
            x=recv[i][0]-ax.a;
            y=recv[i][1]-ay.a;
            a=sqrt((x*x)+(y*y));    
            dt[i]=a/v;              

        }
        
        a=dt[0]; 
        for (i=1;i<n;i++) 
            if (a>dt[i]) 
                a=dt[i];
        for (i=0;i<n;i++) 
            dt[i]-=a;

        e=0.0; 
        for (i=0;i<n;i++) 
            e+=fabs(recv[i][2]-dt[i]);
    }

    pos[0]=ax.aa;
    pos[1]=ay.aa;
}

Admittedly, my Python is a bit rusty. What would be the Python 'equivalent' of these nested loops? It isn't clear to me how this could be done with a Python for loop. I'm not really sure where to begin.

I haven't included the Approximate class here as it is rather lengthy and, I think, irrelevant, although I'd be happy to share if that would be useful. Approximate is an approximation search class. done is (obviously) a boolean, indicating when a solution has been found and the algorithm should terminate and print the solution, ax.a and ay.a (not to be confused with ax.aa and ay.aa).

Please let me know if any additional information would be helpful. I'm trying to maintain a balance of providing enough information such that this is a well-defined question, and not so much as to overwhelm the reader where this is (probably) a simple problem.

Barmar
  • 741,623
  • 53
  • 500
  • 612
10GeV
  • 453
  • 2
  • 14
  • You can convert the first 2 for loops to while. The inner for loops incrementing i from 0 to n can be done using for i in range(n): – whiplash Oct 22 '20 at 00:09
  • @ArunSubramanian I do not think so (unless you can code the iteration step on the run) as its not a standard loop (that just increments by constant) instead its more like binary search but slightly more complex ... here [more info](https://stackoverflow.com/a/36163847/2521214) ... – Spektre Nov 07 '20 at 07:21

1 Answers1

3

Without knowing much about what Approximate does, the most likely solution here would be to implement the class as an iterable in Python, where the __iter__ method is implemented as a generator function.

The uncertainty lies in how much interdependence you've got here; the init method you're using takes the address-of e (and you've provided no indication of what it might do with it; is it an input parameter, output parameter, or both?), while you're simultaneously mutating e in the body of your loop. If it's an input parameter (so the modifications to e in the body of the loop have meaning), then this will be harder to implement in Python (though making __iter__ into a true coroutine where you send in values sometimes might be possible). If it's only an output parameter (initializing e to some value, but not using the modifications from the body of the loop) that's easier to do (but also not likely to be true, since it would make the sharing of e between both Approximates weirder).

Basically, you're already not doing a "normal" C++ iterator design, and C++ iterators come from a fairly different mindset from the one behind Python iterators. You're going to need to refactor at least a little to produce vaguely Pythonic code, and generators are almost certain to be involved.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • 1
    My guess is that `e` is an "epsilon" parameter for approximate matching. It's passed as an address because the loop updates it each iteration: `e += fabs(recv[i][2]-dt[i]);` – Barmar Oct 22 '20 at 00:18
  • The pythonic way to do that would probably to make it an attribute of the iterable object, and use `ax.e += ...` – Barmar Oct 22 '20 at 00:19
  • @Barmar: Maybe. Though in the C++ code that `e` is shared between the outer loop `Approximate`, the inner loop `Approximate`, and the inner loop body. So unless you wrote another custom class to represent it (something where `+=` would modify it in place, unlike built-in numeric types that are immutable), you'd have some work (and likely pretty ugly code) keeping it in sync among all three points of use. – ShadowRanger Oct 22 '20 at 00:31
  • @Barmar While I don't have the source for the `Approximate` class on hand at the moment, it's very close to (and drew inspiration from) this class: https://pastebin.com/MFVsfgyT (I'll get attribution for that briefly). As they are standard, all naming conventions are the same. And, yes, as you pointed out, it's passed as an address since the loop updates with each iteration. So, in Python, I think you suggestion on using an attribute of the iterable object is the best path (unless someone has a better suggestion) – 10GeV Oct 22 '20 at 01:51
  • @Barmar Yes the `ax.e` is optimization problem epsilon (or error, distance whatever) ... the nested classes do not need to be in sync in between each of them they just need actually iterated error value when their function `step` is called so it might be a parameter of the `step(e)`... I used pointer instead to speed up the process as any parameter will cause heap trashing and the step is called many times ...for more info see [How approximation search works](https://stackoverflow.com/a/36163847/2521214) – Spektre Nov 07 '20 at 07:27