Fault trees structure
Arturo PĆ©rez Mulas
arturo_perez at wanadoo.es
Tue Dec 12 14:16:32 EST 2000
Hi,
I have not left the discussion, only I have not yet have the time to read
you guys.
However, on a first look, it seems to me that Darrel's model is only
including 1 or 0
values, while a fault-tree uses probabilities for the limiting nodes (Basic
Events),
and the following arithmetic
Let A and B be nodes of probabilities P(A) and P(B) respectively
then
P(A AND B) = P(A) * P(B)
P(A OR B) = P(A) + P(B) - P(A)*P(B)
And also the following boolean logic (I use '+' for OR and '*' for AND):
A + (A * B) = A
A * (A + B) = A + A*B = A
And for logic '1' and '0', the usual
A + '0' = A
A * '0' = '0'
A + '1' = '1'
A * '1' = 'A'
However, this is not the main goal of the structure I want to develop
(believe me,
probability calculation of a FT is an exponential problem -NP- which
requires much
more evolved calculations methods, and approximations)
Also, you are not considering the 'links' issue (I think, sorry I did not
look at it in detail yet!).
Arturo.
"Darrell Gallion" <darrell at dorb.com> escribiĆ³ en el mensaje
news:915pu2$6gf$1 at news.kodak.com...
> Alex Martelli wrote:
> > def connectInput(self, name):
> > self.__dict__.setdefault('_input',{})[name] = None
> >
> > is a possible alternative (also in other cases), but
> > not very readable. It would seem best to just set
> > empty dictionaries in __init__ for _input and _output,
> > so as to avoid having test for them at every connect,
> > and possibly having errors lurking elsewhere, too:
> >
> Sounds good.
> This wasn't required once I moved the __init__ into NodeBase by your
> suggestion.
>
> [snip]
> >
> > Of course, giving NodeBase an __init__ means having
> > to call it in lieu, or from, specific subclasses'
> > ones, but that seems OK; right now OrNode and
> > AndNode sport identical __init__ methods, so why
> > not factor them out of the subclasses and up into
> > the NodeBase common baseclass.
> >
> Done.
>
> >
> >
> > > def logic(self, collection):
> > > cc= reduce(lambda x,y: x and y, self._input.values())
> > > self.propagate(collection, cc)
> >
> > If the values are constrained to "boolean" (0 and 1), then
> > using operator.and_ as the first argument to reduce might
> > well be faster, and perhaps more readable (similarly for
> > or-nodes).
> >
> Not sure that values will be constrained to boolean.
>
> When I tried this something odd happened.
> None isn't valid for and_ while it is for "and"
>
> >>> and_(1, 1)
> 1
> >>> and_(None, 1)
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> TypeError: bad operand type(s) for &
> >>> None and 1
> >>>
>
> Made some other changes as well.
> Thanks for taking the time to look this over.
> Maybe I'll have find a use for this code :)
>
> --Darrell
>
>
> class NodeBase:
> def __init__(self, name, logicFunc):
> self._name=name
> self._previousOutputValue=None
> self._logicFunc=logicFunc
> self._output={}
> self._input={}
>
> def name(self):
> return self._name
>
> def connectInput(self, name):
> self._input[name] = None
>
> def connectOutput(self, otherNode, name):
> self._output[otherNode.name()] = name
> otherNode.connectInput(name)
>
> def signal(self, collection, name, value=1):
> self._input[name]=value
> self.logic(collection)
>
> def propagate(self, collection, value):
> if value==self._previousOutputValue:
> # No point in propagating the same value
> return
> for nodeName, inputName in self._output.items():
> try:
> node=getattr(collection, nodeName)
> node.signal(collection, inputName, value)
> except:
> print self._name
> print nodeName
> print collection
> raise
>
> def logic(self, collection):
> cc= self._logicFunc(self, collection)
> self.propagate(collection, cc)
>
> def andFunc(self, collection):
> return reduce(lambda x,y: x and y, self._input.values())
>
> def announceFunc(self, collection):
> cc= reduce(lambda x,y: x or y, self._input.values())
> if cc:
> print self._name, self._input
> else:
> # Noise on the input, but nothing to report
> print '.',
> return cc
>
> def sourceFunc(self, collection):
> assert(0)
>
> class SourceNode(NodeBase):
> def __init__(self, name):
> NodeBase.__init__(self, name, sourceFunc)
>
> def __call__(self, collection, value):
> self.propagate(collection, value)
>
>
> class FaultTree:#(UserDict.UserDict): Not sure about this
> def __init__(self, *nodes):
> for n in nodes:
> setattr(self, n.name(), n)
>
> ft=FaultTree(NodeBase("and1", andFunc), NodeBase("and2", andFunc),
> NodeBase("and3", andFunc),
> NodeBase("fail", announceFunc))
>
> ft.and1.connectOutput(ft.and3,"one")
> ft.and2.connectOutput(ft.and3,"two")
> ft.and3.connectOutput(ft.fail,"who cares")
>
> # Setup some signal sources
> drivers=[]
> for x in range(3):
> s1=SourceNode(x)
> drivers.append(s1)
> s1.connectOutput(ft.and1, x)
>
> # Setup some signal sources
> for x in range(3):
> s1=SourceNode(x)
> drivers.append(s1)
> s1.connectOutput(ft.and2, x)
>
> # Make it go
> for i in drivers:
> i(ft, 1)
>
>
>
>
More information about the Python-list
mailing list