Skip to content

Commit

Permalink
[Fix #116] Implement fault tree evaluation using operational data and…
Browse files Browse the repository at this point in the history
… operational data filter

- Add BaseRepositoryService.getToolContext to get aa FTA tool specific context for a given URI. This is used to generate an FTA tool specific context for a given system uri where the tool can store all system related entities created by the tool, e.g. global operational failure rate estimates, system specific operational data filters.
  • Loading branch information
kostobog committed Jun 19, 2024
1 parent b34f756 commit ef5f593
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package cz.cvut.kbss.analysis.dao;

import cz.cvut.kbss.analysis.config.conf.PersistenceConf;
import cz.cvut.kbss.analysis.model.FailureRateEstimate;
import cz.cvut.kbss.analysis.service.IdentifierService;
import cz.cvut.kbss.analysis.util.Vocabulary;
import cz.cvut.kbss.jopa.model.EntityManager;
import org.springframework.stereotype.Repository;

import java.net.URI;

@Repository
public class FailureRateEstimateDao extends BaseDao<FailureRateEstimate>{
protected final static URI HAS_ESTIMATE_PROP = URI.create(Vocabulary.s_p_has_estimate);
protected final static URI VALUE_PROP = URI.create(Vocabulary.s_p_value);

public FailureRateEstimateDao(EntityManager em, PersistenceConf config, IdentifierService identifierService) {
super(FailureRateEstimate.class, em, config, identifierService);
}

public void setHasEstimate(URI failureRateUri, FailureRateEstimate estimate, URI context) {
addOrReplaceValue(failureRateUri, HAS_ESTIMATE_PROP, estimate.getUri(), context);
}

public void setValue(URI failureRateEstimateUri, Double value, URI context) {
addOrReplaceValue(failureRateEstimateUri, VALUE_PROP, value, context);
}
}
6 changes: 6 additions & 0 deletions src/main/java/cz/cvut/kbss/analysis/dao/FaultEventDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
@Repository
public class FaultEventDao extends NamedEntityDao<FaultEvent> {

public static final URI PROBABILITY_PROP = URI.create(Vocabulary.s_p_probability);

@Autowired
protected FaultEventDao(EntityManager em, PersistenceConf config, IdentifierService identifierService) {
super(FaultEvent.class, em, config, identifierService);
Expand Down Expand Up @@ -52,6 +54,10 @@ protected EntityDescriptor getEntityDescriptorInContext(URI graph){
return entityDescriptor;
}

public void setProbability(URI faultEventUri, Double probability, URI context){
addOrReplaceValue(faultEventUri, PROBABILITY_PROP, probability, context);
}

public EntityDescriptor getRectangleDescriptor(URI uri){
URI graph = getContext(uri);
EntityDescriptor entityDescriptor = new EntityDescriptor(graph);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,4 +271,11 @@ protected void validate(T instance) {
}
}

public URI getToolContext(URI uri){
return getToolContext(uri.toString());
}

public URI getToolContext(String uri){
return URI.create(uri + "-jopa");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import cz.cvut.kbss.analysis.dao.*;
import cz.cvut.kbss.analysis.exception.EntityNotFoundException;
import cz.cvut.kbss.analysis.model.*;
import cz.cvut.kbss.analysis.model.ava.ATASystem;
import cz.cvut.kbss.analysis.model.ava.FHAEventType;
import cz.cvut.kbss.analysis.model.diagram.Rectangle;
import cz.cvut.kbss.analysis.model.fta.CutSetExtractor;
Expand Down Expand Up @@ -45,7 +46,7 @@ public class FaultTreeRepositoryService extends ComplexManagedEntityRepositorySe
private final FailureModeDao failureModeDao;
private final OperationalDataService operationalDataService;
private final FaultEventTypeService faultEventTypeService;
private final FaultEventTypeDao faultEventTypeDao;
private final FailureRateEstimateDao failureRateEstimateDao;

@Autowired
public FaultTreeRepositoryService(@Qualifier("defaultValidator") Validator validator,
Expand All @@ -61,7 +62,7 @@ public FaultTreeRepositoryService(@Qualifier("defaultValidator") Validator valid
FailureModeDao failureModeDao,
OperationalDataService operationalDataService,
FaultEventTypeService faultEventTypeService,
FaultEventTypeDao faultEventTypeDao) {
FailureRateEstimateDao failureRateEstimateDao) {
super(validator, userDao, securityUtils);
this.faultTreeDao = faultTreeDao;
this.faultEventScenarioDao = faultEventScenarioDao;
Expand All @@ -73,7 +74,7 @@ public FaultTreeRepositoryService(@Qualifier("defaultValidator") Validator valid
this.failureModeDao = failureModeDao;
this.operationalDataService = operationalDataService;
this.faultEventTypeService = faultEventTypeService;
this.faultEventTypeDao = faultEventTypeDao;
this.failureRateEstimateDao = failureRateEstimateDao;
}

@Override
Expand Down Expand Up @@ -535,62 +536,84 @@ public FaultTree performCutSetAnalysis(URI faultTreeUri){
return faultTree;
}

/**
* Updates the provided fault tree sns' failures with operational failure rate calculated based on filter. The update
* is reflected in the persistent storage and in the input fault tree.
*
* The procedure can be summarized as follows:
* 1. Extracts sns failures from input fault tree
* 2. Fetches operational failure rate taking based on provided filter for sns failures in the supplied faultTree
* 3. Updates operational estimates of sns failures in the provided tree
* 4. Updates fault event probabilities of sns fault events which have selected operational failure rate.
*
* @param faultTree
* @param filter
*/
@Transactional
public FaultTree evaluate(URI faultTreeUri, OperationalDataFilter filter) {

operationalDataFilterService.updateFaultTreeFilter(faultTreeUri, filter);

FaultTree faultTree = findWithDetails(faultTreeUri);

updateFaultTreeOperationalFailureRates(faultTree, filter);

return evaluate(faultTree);
}

protected void updateFaultTreeOperationalFailureRates(FaultTree faultTree, OperationalDataFilter filter){
public void updateFaultTreeOperationalFailureRates(FaultTree faultTree, OperationalDataFilter filter) {
URI faultTreeUri = faultTree.getUri();
// fetch get map between SNS component uris and fault events which will store the calculated failure rate
Map<URI, Pair<FaultEvent, Event>> map = new HashMap<>();
faultTree.getAllEvents().stream()
.filter(e -> e.getEventType() == FtaEventType.BASIC && e.getSupertypes() != null && !e.getSupertypes().isEmpty())
.flatMap(e -> e.getSupertypes().stream().map(t -> Pair.of(e,t))).forEach(p -> {
URI componentURI = Optional.ofNullable(p.getFirst().getBehavior())
.flatMap(e -> e.getSupertypes().stream().map(t -> {
Event type = null;

if(t.getSupertypes() != null) {
type = t.getSupertypes().stream()
.filter(st -> Optional.ofNullable(st.getBehavior())
.map(b -> b.getItem() instanceof ATASystem)
.isPresent()).findFirst().orElse(null);
}

// TODO - workaround - using system specific event when general ROLE event is missing.
if(type == null)
type = t;

return Pair.of(e, type);
})).forEach(p -> {
URI componentURI = Optional.ofNullable(p.getSecond().getBehavior())
.map(b -> b.getItem())
.map(i -> i.getUri())
.orElse(null);
if(componentURI != null)
map.put(componentURI, p);
});

if (map.isEmpty())
return;

ItemFailureRate[] operationalFailureRateEstimates = operationalDataService.fetchFailureRates(filter, map.keySet());

URI systemContext = getToolContext(faultTree.getSystem().getUri());
for(ItemFailureRate estimate : operationalFailureRateEstimates){
if(estimate.getFailureRate() == null)
continue;
Pair<FaultEvent, Event> p = map.get(estimate.getUri());
FaultEvent ft = p.getFirst();
FailureRate fr = ((FaultEventType)p.getSecond()).getFailureRate();

FaultEventType evt = (FaultEventType) p.getSecond();
FailureRateEstimate frEstimate = evt.getFailureRate().getEstimate();
if(frEstimate == null){
frEstimate = new FailureRateEstimate();
evt.getFailureRate().setEstimate(frEstimate);
}

evt.getFailureRate().getEstimate().setValue(estimate.getFailureRate());

evt.getFailureRate().setContext(faultTreeUri);
faultEventTypeDao.update(evt);

if(ft.getSelectedEstimate() != null &&
ft.getSelectedEstimate().getUri() != null &&
ft.getSelectedEstimate().getUri().equals(frEstimate.getUri())) {
updateOperationalFailureRate(systemContext, faultTreeUri, estimate, ft, fr);
}
}

ft.setProbability(frEstimate.getValue());
protected void updateOperationalFailureRate(URI systemContext, URI faultTreeUri, ItemFailureRate estimate, FaultEvent ft, FailureRate fr){
FailureRateEstimate frEstimate = fr.getEstimate();
if(frEstimate == null) {
frEstimate = new FailureRateEstimate();
frEstimate.setValue(estimate.getFailureRate());
frEstimate.setContext(systemContext);
failureRateEstimateDao.persist(frEstimate);
failureRateEstimateDao.setHasEstimate(fr.getUri(), frEstimate, systemContext);
fr.setEstimate(frEstimate);
}else{
frEstimate.setValue(estimate.getFailureRate());
failureRateEstimateDao.setValue(frEstimate.getUri(), estimate.getFailureRate(), systemContext);
}

ft.setContext(faultTreeUri);
faultEventDao.update(ft);
}
if(ft.getSelectedEstimate() != null && ft.getSelectedEstimate().equals(frEstimate.getUri())) {
ft.setProbability(frEstimate.getValue());
faultEventDao.setProbability(ft.getUri(), frEstimate.getValue(), faultTreeUri);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public OperationalDataFilter getFaultTreeFilter(URI faultTreeURI, URI systemURI)

@Transactional
public void updateSystemFilter(URI systemURI, OperationalDataFilter newFilter){
URI context = URI.create(systemURI.toString() + "-jopa");
URI context = getToolContext(systemURI);
updateFilter(systemURI, newFilter, context);
}

Expand Down

0 comments on commit ef5f593

Please sign in to comment.