 # Resistive circuit calculation

Hello everybody,

i’m quite new to prolog and looking at a practice project:

I came up with different code for paths and calculating row and parallel resitances.

Currently my biggest issue seems to be, how to find out in this grid, or another random grid, if the next resistance is parallel or in row without them being predefined as such, how to save that result to use it in further calculation and how to make use of the split and fusion.

This is what i have sofar:

Currently i seem to be missing an important thought to make it work, and probably some coding skills aswell. Would appreciate any help!

Thanks in advance, kind regards and stay healthy!

So i worked on the code a bit and changed some of it. Here is what i got:

For the algorithm, in this specific example it would work to look at the number of possible paths which is max 2.
If the amount of paths is 1, it has to be serial.
If the amount of paths is 2, the path with 1 more member and its position has to be identified.
For example:
a->d
= P1 = a->b->c->d (a->b->c is a row of serial resistors)
P2 = a->c>d (a->c is paralell to the section of P1)

I am not sure yet how to do the needed operations on those paths.
Another problem is that i was not able to think of a solution to handle bigger circuits with more than two possible paths.

Any ideas would be very welcome

I think you may get more input if you provided a specification of the problem, i.e., given your network model as a list of resistances (resistance=a resistor connecting two nodes), what question are you attempting to answer?

One possibility: Find a single “resistance” which is equivalent to the network.

Presented with this problem, I would try to find two resistances in the list that could be combined (parallel or serial). Then replace the two in the list with their equivalent single resistance and recurse until I was left with a single value.

But maybe that’s not your “question”.

That’s exactly the question. Find a single resistance which is equivalent to the network.

Given informations are:

Resistance between two nodes: e.g.
(a,500,b)
(b,50,c)
(a,550,c)
Splits and joints in the network:
split(a)

The splits seem to be of no use to me since, depending on where you start and where you want to go, splits are no longer splits but simply part of resistors in a row. But maybe i’m just not seeing why this would still be usefull.

For smaller networks it seems doable. Find all paths from a to b. Compare them. Try to find rules for resistors in parallel and in row. Combine and replace in the list.

As soon as more then two paths are available and the differences get way bigger i’m lost on what the algorithem should be.

OK, my suggestions:

I think the data model is fairly straight forward: a resistor network is defined by a list of resistor instances which can be represented by term of the form:

``````resistance(N1,R,N2)
``````

or something similar. `N1` and `N2` are node labels, e.g., atoms like `a`, `b`, etc. and `R` is the resistor value (a number). To keep things simple for now let’s assume `N1 @< N2`, i.e., the labels are ordered, which can be done without any loss of generality.

The objective is to find “single resistance which is equivalent to the network”. One way of doing this is to iteratively replace a pair of resistors in the network by a single resistor until the network list consists of a single resistor. A slightly more general predicate might combine pairs of resistors until a minimum network is achieved, i.e., no further combinations can be found:

``````res_reduce(Rs,R) :-
res_combine(Rs,NRs),    % combine two into one
res_reduce(NRs,R).      % and repeat
res_reduce(Rs,Rs).          % minimal network
``````

So now the trick is to write rules which find and replace a pair of resistors in the list with a single value. Such a rule for parallel resistors might look like:

``````res_combine(Rs,[resistance(N1,Rn,N2)|NRs]) :-
select(resistance(N1,R1,N2),Rs,Rs1),
select(resistance(N1,R2,N2),Rs1,NRs),
!,  % avoid duplicates due to order selected
Rn is (R1*R2)/(R1+R2).
``````

This uses `select/3` from `library(lists)` which is autoloaded. If you’re going to use lists, this library provides many useful predicates.

The `res_combine` rule for serial resistors is a little more complicated since it effectively removes a node from the network and you have to make sure no other resistor is connected to that node, but I’ll leave it to you as an exercise.

Example queries using your test network (using `res_network` to define the network):

``````?- res_network(Rs),res_reduce(Rs,[EqR]).
Rs = [resistance(a, 100, c), resistance(a, 200, b), resistance(b, 300, c), resistance(c, 50, d)],
EqR = resistance(b, 200, d) ;
Rs = [resistance(a, 100, c), resistance(a, 200, b), resistance(b, 300, c), resistance(c, 50, d)],
EqR = resistance(a, 400r3, d) ;
false.

?- res_network(Rs),res_reduce(Rs,[resistance(a,R,T)]).
Rs = [resistance(a, 100, c), resistance(a, 200, b), resistance(b, 300, c), resistance(c, 50, d)],
R = 400r3,
T = d ;
false.
``````

The first query finds two equivalent resistance values: `200` ohms between `b` and `d` and `400r3` (`133.33..`) ohms between `a` and `c`. The second query looks for the equivalent resistance connected to node `a`.

Does something like this meet your needs?