TeDDy 4.1.0
Decision diagram library.
Loading...
Searching...
No Matches
reliability_manager.hpp
1#ifndef LIBTEDDY_DETAILS_RELIABILITY_MANAGER_HPP
2#define LIBTEDDY_DETAILS_RELIABILITY_MANAGER_HPP
3
4#include <libteddy/details/diagram_manager.hpp>
5#include <libteddy/details/dplds.hpp>
6#include <libteddy/details/probabilities.hpp>
7
8#include <concepts>
9#include <iterator>
10#include <unordered_map>
11#include <utility>
12#include <variant>
13#include <vector>
14
15namespace teddy
16{
17namespace details
18{
19template<class Degree>
20concept is_bss = std::same_as<degrees::fixed<2>, Degree>;
21}
22
28{
29 int32 index_;
30 int32 from_;
31 int32 to_;
32};
33
41template<class Degree, class Domain>
42class reliability_manager : public diagram_manager<double, Degree, Domain>
43{
44public:
45 using diagram_t =
47 // TODO ^^^^^^
48 // details::bytes<max(sizeof(double),
49 // sizeof(expr))>
50
51public:
63 template<probs::prob_vector Ps>
65 auto calculate_probabilities (Ps const& probs, diagram_t const& diagram)
66 -> void;
67
79 template<probs::prob_matrix Ps>
80 auto calculate_probabilities (Ps const& probs, diagram_t const& diagram)
81 -> void;
82
94 template<probs::prob_vector Ps>
96 auto calculate_probability (Ps const& probs, diagram_t const& diagram)
97 -> double;
98
111 template<probs::prob_matrix Ps>
113 int32 state,
114 Ps const& probs,
115 diagram_t const& diagram
116 ) -> double;
117
130 [[nodiscard]] auto get_probability (int32 state) const -> double;
131
143 template<probs::prob_vector Ps, class Foo = void>
145 auto calculate_availability (Ps const& probs, diagram_t const& diagram)
146 -> utils::second_t<Foo, double>;
147
160 template<probs::prob_matrix Ps>
162 int32 state,
163 Ps const& probs,
164 diagram_t const& diagram
165 ) -> double;
166
179 template<class Foo = void>
181 [[nodiscard]] auto get_availability () const
182 -> utils::second_t<Foo, double>;
183
198 [[nodiscard]] auto get_availability (int32 state) const -> double;
199
211 template<probs::prob_matrix Ps, class Foo = void>
213 auto calculate_unavailability (Ps const& probs, diagram_t const& diagram)
214 -> utils::second_t<Foo, double>;
215
228 template<probs::prob_matrix Ps>
230 int32 state,
231 Ps const& probs,
232 diagram_t const& diagram
233 ) -> double;
234
247 template<class Foo = void>
249 auto get_unavailability () -> utils::second_t<Foo, double>;
250
266 [[nodiscard]] auto get_unavailability (int32 state) -> double;
267
268#ifdef LIBTEDDY_SYMBOLIC_RELIABILITY
269 // TODO cmp post a level verzie
270
274 template<class Ps>
275 auto symbolic_probability (
276 int32 state,
277 Ps const& probs,
278 diagram_t const& diagram
279 ) -> symprobs::expression;
280
284 template<class Ps>
285 auto symbolic_availability (
286 int32 state,
287 Ps const& probs,
288 diagram_t const& diagram
289 ) -> symprobs::expression;
290
294 template<class Ps>
295 auto unsymbolic_availability (
296 int32 state,
297 Ps const& probs,
298 diagram_t const& diagram
299 ) -> symprobs::expression;
300#endif
301 // TODO calculate_state_frequency
308 auto state_frequency (diagram_t const& diagram, int32 state) -> double;
309
317 template<class FChange>
318 auto dpld (var_change varChange, FChange fChange, diagram_t const& diagram)
319 -> diagram_t;
320
328 auto to_dpld_e (int32 varFrom, int32 varIndex, diagram_t const& dpld)
329 -> diagram_t;
330
340 auto structural_importance (diagram_t const& dpld) -> double;
341
352 template<probs::prob_matrix Ps>
353 auto birnbaum_importance (Ps const& probs, diagram_t const& dpld) -> double;
354
368 template<probs::prob_matrix Ps>
370 Ps const& probs,
371 diagram_t const& dpld,
372 double unavailability,
373 int32 componentState,
374 int32 componentIndex
375 ) -> double;
376
390 template<out_var_values Vars>
391 auto mcvs (diagram_t const& diagram, int32 state) -> std::vector<Vars>;
392
406 template<out_var_values Vars>
407 auto mpvs (diagram_t const& diagram, int32 state) -> std::vector<Vars>;
408
423 template<out_var_values Vars, std::output_iterator<Vars> Out>
424 auto mcvs_g (diagram_t const& diagram, int32 state, Out out) -> void;
425
440 template<out_var_values Vars, std::output_iterator<Vars> Out>
441 auto mpvs_g (diagram_t const& diagram, int32 state, Out out) -> void;
442
443protected:
445 int32 varCount,
446 int64 nodePoolSize,
447 int64 overflowNodePoolSize,
448 std::vector<int32> order
449 )
451
453 int32 varCount,
454 int64 nodePoolSize,
455 int64 overflowNodePoolSize,
456 domains::mixed domain,
457 std::vector<int32> order
458 )
460
461private:
462 using node_t = typename diagram_manager<double, Degree, Domain>::node_t;
463 using son_conainer = typename node_t::son_container;
464
465 // TODO not nice
466 // same problem as n-ary apply, we will see...
467
468 struct dpld_cache_entry
469 {
470 node_t* lhs_;
471 node_t* rhs_;
472 };
473
474 struct cache_entry_hash
475 {
476 auto operator() (dpld_cache_entry const& entry) const
477 {
478 return utils::pack_hash(entry.lhs_, entry.rhs_);
479 }
480 };
481
482 struct cache_entry_equals
483 {
484 auto operator() (
485 dpld_cache_entry const& lhs,
486 dpld_cache_entry const& rhs
487 ) const
488 {
489 return lhs.lhs_ == rhs.lhs_ && lhs.rhs_ == rhs.rhs_;
490 }
491 };
492
493 using dpld_cache = std::unordered_map<
494 dpld_cache_entry,
495 node_t*,
496 cache_entry_hash,
497 cache_entry_equals>;
498
499private:
500 auto to_mnf (diagram_t const& diagram) -> diagram_t;
501
502 auto to_mnf_impl (std::unordered_map<node_t*, node_t*>& memo, node_t* node)
503 -> node_t*;
504
505 template<class FChange>
506 auto dpld_impl (
507 dpld_cache& cache,
508 var_change varChange,
509 FChange fChange,
510 node_t* lhs,
511 node_t* rhs
512 ) -> node_t*;
513
514 auto to_dpld_e_impl (
515 std::unordered_map<node_t*, node_t*>& memo,
516 int32 varFrom,
517 int32 varIndex,
518 node_t* node
519 ) -> node_t*;
520
521 template<probs::prob_matrix Ps>
522 auto calculate_ntps_post_impl (
523 std::vector<int32> const& selected,
524 Ps const& probs,
525 node_t* root
526 ) -> double;
527
528 template<probs::prob_matrix Ps>
529 auto calculate_ntps_level_impl (Ps const& probs, node_t* root) -> void;
530};
531
532template<class Degree, class Domain>
533template<probs::prob_vector Ps>
534requires(details::is_bss<Degree>)
536 Ps const& probs,
537 diagram_t const& diagram
538) -> void
539{
540 this->calculate_probabilities(
542 diagram
543 );
544}
545
546template<class Degree, class Domain>
547template<probs::prob_matrix Ps>
549 Ps const& probs,
550 diagram_t const& diagram
551) -> void
552{
553 this->calculate_ntps_level_impl(probs, diagram.unsafe_get_root());
554}
555
556template<class Degree, class Domain>
557template<probs::prob_vector Ps>
558requires(details::is_bss<Degree>)
560 Ps const& probs,
561 diagram_t const& diagram
562) -> double
563{
564 return this->calculate_probability(
565 1,
567 diagram
568 );
569}
570
571template<class Degree, class Domain>
572template<probs::prob_matrix Ps>
574 int32 const state,
575 Ps const& probs,
576 diagram_t const& diagram
577) -> double
578{
579 return this
580 ->calculate_ntps_post_impl({state}, probs, diagram.unsafe_get_root());
581}
582
583template<class Degree, class Domain>
585) const -> double
586{
587 node_t* const node = this->nodes_.get_terminal_node(state);
588 return node ? node->get_data() : 0.0;
589}
590
591template<class Degree, class Domain>
592template<probs::prob_vector Ps, class Foo>
595 Ps const& probs,
596 diagram_t const& diagram
597) -> utils::second_t<Foo, double>
598{
599 return this->calculate_availability(
600 1,
602 diagram
603 );
604}
605
606template<class Degree, class Domain>
607template<probs::prob_matrix Ps>
609 int32 const state,
610 Ps const& probs,
611 diagram_t const& diagram
612) -> double
613{
614 std::vector<int32> states;
615 this->nodes_.for_each_terminal_node(
616 [state, &states] (node_t* const node)
617 {
618 if (node->get_value() >= state)
619 {
620 states.push_back(node->get_value());
621 }
622 }
623 );
624 return this
625 ->calculate_ntps_post_impl(states, probs, diagram.unsafe_get_root());
626}
627
628template<class Degree, class Domain>
629template<class Foo>
632 -> utils::second_t<Foo, double>
633{
634 node_t* const node = this->nodes_.get_terminal_node(1);
635 return node ? node->get_data() : 0;
636}
637
638template<class Degree, class Domain>
640) const -> double
641{
642 double result = 0;
643 this->nodes_.for_each_terminal_node(
644 [state, &result] (node_t* const node)
645 {
646 if (node->get_value() >= state)
647 {
648 result += node->get_data();
649 }
650 }
651 );
652 return result;
653}
654
655template<class Degree, class Domain>
656template<probs::prob_matrix Ps, class Foo>
659 Ps const& probs,
660 diagram_t const& diagram
661) -> utils::second_t<Foo, double>
662{
663 return this->calculate_unavailability(1, probs, diagram);
664}
665
666template<class Degree, class Domain>
667template<probs::prob_matrix Ps>
669 int32 const state,
670 Ps const& probs,
671 diagram_t const& diagram
672) -> double
673{
674 std::vector<int32> states;
675 this->nodes_.for_each_terminal_node(
676 [state, &states] (node_t* const node)
677 {
678 if (node->get_value() < state)
679 {
680 states.emplace_back(node->get_value());
681 }
682 }
683 );
684 return this
685 ->calculate_ntps_post_impl(states, probs, diagram.unsafe_get_root());
686}
687
688template<class Degree, class Domain>
689template<class Foo>
692 -> utils::second_t<Foo, double>
693{
694 return this->get_unavailability(1);
695}
696
697template<class Degree, class Domain>
699 -> double
700{
701 double result = 0;
702 this->nodes_.for_each_terminal_node(
703 [state, &result] (node_t* const node)
704 {
705 if (node->get_value() < state)
706 {
707 result += node->get_data();
708 }
709 }
710 );
711 return result;
712}
713
714#ifdef LIBTEDDY_SYMBOLIC_RELIABILITY
715
719template<class Degree, class Domain>
720template<class Ps>
722 int32 state,
723 Ps const& probs,
724 diagram_t const& diagram
725) -> symprobs::expression
726{
727 // TODO store it in the nodes
728 std::unordered_map<node_t*, GiNaC::ex> exprMap;
729
730 this->nodes_.for_each_terminal_node(
731 [&exprMap, state] (node_t* const node)
732 {
733 GiNaC::ex val(static_cast<double>(
734 static_cast<int32>(node->get_value() >= state)
735 ));
736 exprMap.emplace(std::make_pair(node, val));
737 }
738 );
739
740 node_t* const root = diagram.unsafe_get_root();
741 this->nodes_.traverse_post(
742 root,
743 [this, &probs, &exprMap] (node_t* const node) mutable
744 {
745 if (not node->is_terminal())
746 {
747 auto [it, isIn]
748 = exprMap.emplace(std::make_pair(node, GiNaC::ex(0.0)));
749 assert(isIn);
750 GiNaC::ex& expr = it->second;
751 int32 const nodeIndex = node->get_index();
752 int32 const domain = this->nodes_.get_domain(nodeIndex);
753 for (int32 k = 0; k < domain; ++k)
754 {
755 node_t* const son = node->get_son(k);
756 expr += exprMap.find(son)->second
757 * probs[as_uindex(nodeIndex)][as_uindex(k)]
758 .as_underlying_unsafe();
759 }
760 }
761 }
762 );
763 return symprobs::expression(exprMap.find(root)->second);
764}
765
766#endif
767
768template<class Degree, class Domain>
770 diagram_t const& diagram,
771 int32 state
772) -> double
773{
774 int32 const indexFrom = 0;
775 int32 const indexTo = this->get_var_count();
776 int64 const domainSize = this->nodes_.domain_product(indexFrom, indexTo);
777 return static_cast<double>(this->satisfy_count(state, diagram))
778 / static_cast<double>(domainSize);
779}
780
781template<class Degree, class Domain>
782template<class FChange>
784 var_change varChange,
785 FChange fChange,
786 diagram_t const& diagram
787) -> diagram_t
788{
789 // TODO vector cache?
790 dpld_cache cache;
791 node_t* const oldRoot = diagram.unsafe_get_root();
792 node_t* lhsRoot = oldRoot;
793 node_t* rhsRoot = oldRoot;
794 if (not oldRoot->is_terminal() && oldRoot->get_index() == varChange.index_)
795 {
796 lhsRoot = oldRoot->get_son(varChange.from_);
797 rhsRoot = oldRoot->get_son(varChange.to_);
798 }
799 node_t* const newRoot
800 = this->dpld_impl(cache, varChange, fChange, lhsRoot, rhsRoot);
801 this->nodes_.run_deferred();
802 return diagram_t(newRoot);
803}
804
805template<class Degree, class Domain>
806template<class FChange>
808 dpld_cache& cache,
809 var_change varChange,
810 FChange fChange,
811 node_t* const lhs,
812 node_t* const rhs
813) -> node_t*
814{
815 constexpr auto get_son = [] (node_t* const node,
816 int32 const k,
817 int32 const varIndex,
818 int32 const varValue)
819 {
820 auto const son = node->get_son(k);
821 return son->is_internal() && son->get_index() == varIndex
822 ? son->get_son(varValue)
823 : son;
824 };
825
826 auto const cached = cache.find(dpld_cache_entry(lhs, rhs));
827 if (cached != cache.end())
828 {
829 return cached->second;
830 }
831
832 node_t* result = nullptr;
833
834 if (lhs->is_terminal() && rhs->is_terminal())
835 {
836 result = this->nodes_.make_terminal_node(
837 static_cast<int32>(fChange(lhs->get_value(), rhs->get_value()))
838 );
839 }
840 else
841 {
842 int32 const lhsLevel = this->nodes_.get_level(lhs);
843 int32 const rhsLevel = this->nodes_.get_level(rhs);
844 int32 const topLevel = utils::min(lhsLevel, rhsLevel);
845 int32 const topIndex = this->nodes_.get_index(topLevel);
846 int32 const domain = this->nodes_.get_domain(topIndex);
847 son_conainer sons = this->nodes_.make_son_container(domain);
848 for (int32 k = 0; k < domain; ++k)
849 {
850 node_t* const fst
851 = lhsLevel == topLevel
852 ? get_son(lhs, k, varChange.index_, varChange.from_)
853 : lhs;
854
855 node_t* const snd
856 = rhsLevel == topLevel
857 ? get_son(rhs, k, varChange.index_, varChange.to_)
858 : rhs;
859 sons[k] = this->dpld_impl(cache, varChange, fChange, fst, snd);
860 }
861
862 result = this->nodes_.make_internal_node(topIndex, sons);
863 }
864
865 cache.emplace(dpld_cache_entry(lhs, rhs), result);
866
867 return result;
868}
869
870template<class Degree, class Domain>
872 int32 const varFrom,
873 int32 const varIndex,
874 diagram_t const& dpld
875) -> diagram_t
876{
877 node_t* const root = dpld.unsafe_get_root();
878 int32 const rootLevel = this->nodes_.get_level(root);
879 int32 const varLevel = this->nodes_.get_level(varIndex);
880 node_t* newRoot = nullptr;
881
882 if (varLevel < rootLevel)
883 {
884 int32 const varDomain = this->nodes_.get_domain(varIndex);
885 son_conainer sons = this->nodes_.make_son_container(varDomain);
886 for (int32 k = 0; k < varDomain; ++k)
887 {
888 sons[k] = k == varFrom ? root
889 : this->nodes_.make_terminal_node(Undefined);
890 }
891 newRoot = this->nodes_.make_internal_node(varIndex, sons);
892 return diagram_t(newRoot);
893 }
894 else
895 {
896 std::unordered_map<node_t*, node_t*> memo;
897 newRoot = this->to_dpld_e_impl(memo, varFrom, varIndex, root);
898 }
899
900 // TODO run at other places too
901 // TODO add perf to benchmark scripts
902 this->nodes_.run_deferred();
903 return diagram_t(newRoot);
904}
905
906template<class Degree, class Domain>
908 std::unordered_map<node_t*, node_t*>& memo,
909 int32 const varFrom,
910 int32 const varIndex,
911 node_t* const node
912) -> node_t*
913{
914 if (node->is_terminal())
915 {
916 return node;
917 }
918
919 auto const memoIt = memo.find(node);
920 if (memoIt != memo.end())
921 {
922 return memoIt->second;
923 }
924
925 int32 const varDomain = this->nodes_.get_domain(varIndex);
926 int32 const varLevel = this->nodes_.get_level(varIndex);
927 int32 const nodeLevel = this->nodes_.get_level(node);
928 int32 const nodeIndex = this->nodes_.get_index(nodeLevel);
929 int32 const nodeDomain = this->nodes_.get_domain(nodeIndex);
930 son_conainer sons = this->nodes_.make_son_container(nodeDomain);
931 for (int32 k = 0; k < nodeDomain; ++k)
932 {
933 node_t* const son = node->get_son(k);
934 int32 const sonLevel = this->nodes_.get_level(son);
935 if (varLevel > nodeLevel && varLevel < sonLevel)
936 {
937 // A new node goes in between the current node and its k-th son.
938 // Transformation does not need to continue.
939 son_conainer newSons = this->nodes_.make_son_container(varDomain);
940 for (int32 l = 0; l < varDomain; ++l)
941 {
942 newSons[l] = l == varFrom
943 ? son
944 : this->nodes_.make_terminal_node(Undefined);
945 }
946 sons[k] = this->nodes_.make_internal_node(varIndex, newSons);
947 }
948 else
949 {
950 // A new node will be inserted somewhere deeper.
951 sons[k] = this->to_dpld_e_impl(memo, varFrom, varIndex, son);
952 }
953 }
954 node_t* const newNode = this->nodes_.make_internal_node(nodeIndex, sons);
955 memo.emplace(node, newNode);
956 return newNode;
957}
958
959template<class Degree, class Domain>
961 diagram_t const& dpld
962) -> double
963{
964 int32 const indexFrom = 0;
965 int32 const indexTo = this->get_var_count();
966 int64 const domainSize = this->nodes_.domain_product(indexFrom, indexTo);
967 return static_cast<double>(this->satisfy_count(1, dpld))
968 / static_cast<double>(domainSize);
969}
970
971template<class Degree, class Domain>
972template<probs::prob_matrix Ps>
974 Ps const& probs,
975 diagram_t const& dpld
976) -> double
977{
978 return this->calculate_probability(1, probs, dpld);
979}
980
981template<class Degree, class Domain>
982template<probs::prob_matrix Ps>
984 Ps const& probs,
985 diagram_t const& dpld,
986 double const unavailability,
987 int32 const componentState,
988 int32 const componentIndex
989) -> double
990{
991 diagram_t const mnf = this->to_mnf(dpld);
992 double const mnfProbability = this->calculate_probability(1, probs, mnf);
993 double nominator = 0;
994 for (int32 lowerState = 0; lowerState < componentState; ++lowerState)
995 {
996 nominator += probs[as_uindex(componentIndex)][as_uindex(lowerState)];
997 }
998 nominator *= mnfProbability;
999 return nominator / unavailability;
1000}
1001
1002template<class Degree, class Domain>
1003template<out_var_values Vars>
1005 diagram_t const& diagram,
1006 int32 const state
1007) -> std::vector<Vars>
1008{
1009 std::vector<Vars> cuts;
1010 this->mcvs_g<Vars>(diagram, state, std::back_inserter(cuts));
1011 return cuts;
1012}
1013
1014template<class Degree, class Domain>
1015template<out_var_values Vars>
1017 diagram_t const& diagram,
1018 int32 state
1019) -> std::vector<Vars>
1020{
1021 auto cuts = std::vector<Vars>();
1022 this->mcvs_g<Vars>(diagram, state, std::back_inserter(cuts));
1023 return cuts;
1024}
1025
1026template<class Degree, class Domain>
1027template<out_var_values Vars, std::output_iterator<Vars> Out>
1029 diagram_t const& diagram,
1030 int32 const state,
1031 Out out
1032) -> void
1033{
1034 int32 const varCount = this->get_var_count();
1035 std::vector<diagram_t> dpldes;
1036
1037 for (int32 varIndex = 0; varIndex < varCount; ++varIndex)
1038 {
1039 int32 const varDomain = this->nodes_.get_domain(varIndex);
1040 for (int32 varFrom = 0; varFrom < varDomain - 1; ++varFrom)
1041 {
1042 var_change varChange {varIndex, varFrom, varFrom + 1};
1043 diagram_t const dpld
1044 = this->dpld(varChange, dpld::type_3_increase(state), diagram);
1045 dpldes.push_back(this->to_dpld_e(varFrom, varIndex, dpld));
1046 }
1047 }
1048
1049 diagram_t const conj = this->template tree_fold<ops::PI_CONJ>(dpldes);
1050 this->template satisfy_all_g<Vars, Out>(1, conj, out);
1051}
1052
1053template<class Degree, class Domain>
1054template<out_var_values Vars, std::output_iterator<Vars> Out>
1056 diagram_t const& diagram,
1057 int32 const state,
1058 Out out
1059) -> void
1060{
1061 int32 const varCount = this->get_var_count();
1062 std::vector<diagram_t> dpldes;
1063
1064 for (int32 varIndex = 0; varIndex < varCount; ++varIndex)
1065 {
1066 int32 const varDomain = this->nodes_.get_domain(varIndex);
1067 for (int32 varFrom = 1; varFrom < varDomain; ++varFrom)
1068 {
1069 var_change varChange {varIndex, varFrom, varFrom - 1};
1070 diagram_t const dpld
1071 = this->dpld(varChange, dpld::type_3_decrease(state), diagram);
1072 dpldes.push_back(this->to_dpld_e(varFrom, varIndex, dpld));
1073 }
1074 }
1075
1076 diagram_t const conj = this->template tree_fold<ops::PI_CONJ>(dpldes);
1077 this->template satisfy_all_g<Vars, Out>(1, conj, out);
1078}
1079
1080template<class Degree, class Domain>
1081template<probs::prob_matrix Ps>
1083 std::vector<int32> const& selectedValues,
1084 Ps const& probs,
1085 node_t* const root
1086) -> double
1087{
1088 this->nodes_.for_each_terminal_node([] (node_t* const node)
1089 { node->get_data() = 0.0; });
1090
1091 for (int32 const selectedValue : selectedValues)
1092 {
1093 node_t* const node = this->nodes_.get_terminal_node(selectedValue);
1094 if (node)
1095 {
1096 node->get_data() = 1.0;
1097 }
1098 }
1099
1100 this->nodes_.traverse_post(
1101 root,
1102 [this, &probs] (node_t* const node) mutable
1103 {
1104 if (not node->is_terminal())
1105 {
1106 node->get_data() = 0.0;
1107 int32 const nodeIndex = node->get_index();
1108 int32 const domain = this->nodes_.get_domain(nodeIndex);
1109 for (int32 k = 0; k < domain; ++k)
1110 {
1111 node_t* const son = node->get_son(k);
1112 node->get_data()
1113 += son->get_data()
1114 * probs[as_uindex(nodeIndex)][as_uindex(k)];
1115 }
1116 }
1117 }
1118 );
1119 return root->get_data();
1120}
1121
1122template<class Degree, class Domain>
1123template<probs::prob_matrix Ps>
1124auto reliability_manager<Degree, Domain>::calculate_ntps_level_impl(
1125 Ps const& probs,
1126 node_t* const root
1127) -> void
1128{
1129 this->nodes_.traverse_pre(
1130 root,
1131 [] (node_t* const node) { node->get_data() = 0.0; }
1132 );
1133 this->nodes_.for_each_terminal_node([] (node_t* const node)
1134 { node->get_data() = 0.0; });
1135 root->get_data() = 1.0;
1136
1137 this->nodes_.traverse_level(
1138 root,
1139 [this, &probs] (node_t* const node)
1140 {
1141 if (node->is_internal())
1142 {
1143 int32 const nodeIndex = node->get_index();
1144 int32 const domain = this->nodes_.get_domain(nodeIndex);
1145 for (int32 k = 0; k < domain; ++k)
1146 {
1147 node_t* const son = node->get_son(k);
1148 son->get_data()
1149 += node->get_data()
1150 * probs[as_uindex(nodeIndex)][as_uindex(k)];
1151 }
1152 }
1153 }
1154 );
1155}
1156
1157template<class Degree, class Domain>
1158auto reliability_manager<Degree, Domain>::to_mnf(diagram_t const& diagram)
1159 -> diagram_t
1160{
1161 std::unordered_map<node_t*, node_t*> memo;
1162 node_t* const newRoot = this->to_mnf_impl(memo, diagram.unsafe_get_root());
1163 this->nodes_.run_deferred();
1164 return diagram_t(newRoot);
1165}
1166
1167template<class Degree, class Domain>
1168auto reliability_manager<Degree, Domain>::to_mnf_impl(
1169 std::unordered_map<node_t*, node_t*>& memo,
1170 node_t* node
1171) -> node_t*
1172{
1173 if (node->is_terminal())
1174 {
1175 return node;
1176 }
1177
1178 auto const memoIt = memo.find(node);
1179 if (memoIt != memo.end())
1180 {
1181 return memoIt->second;
1182 }
1183
1184 int32 const nodeIndex = node->get_index();
1185 int32 const domain = this->nodes_.get_domain(nodeIndex);
1186 son_conainer sons = this->nodes_.make_son_container(domain);
1187 for (int32 k = 0; k < domain; ++k)
1188 {
1189 node_t* const son = node->get_son(k);
1190 sons[k] = this->to_mnf_impl(memo, son);
1191 }
1192
1193 for (int32 k = domain - 1; k > 0; --k)
1194 {
1195 node_t* const son = sons[k];
1196 if (son->is_terminal() && son->get_value() == 1)
1197 {
1198 for (int32 l = 0; l < k; ++l)
1199 {
1200 sons[l] = son;
1201 }
1202 break;
1203 }
1204 }
1205
1206 for (int32 k = domain - 2; k >= 0; --k)
1207 {
1208 node_t* const son = sons[k];
1209 if (son->is_terminal() && son->get_value() == 0)
1210 {
1211 sons[k] = sons[k + 1];
1212 }
1213 }
1214
1215 node_t* const newNode = this->nodes_.make_internal_node(nodeIndex, sons);
1216 memo.emplace(node, newNode);
1217 return newNode;
1218}
1219
1220template<class Degree, class Domain>
1221reliability_manager<Degree, Domain>::reliability_manager(
1222 int32 const varCount,
1223 int64 const nodePoolSize,
1224 int64 const overflowNodePoolSize,
1225 std::vector<int32> order
1226)
1227requires(domains::is_fixed<Domain>::value)
1228 :
1229 diagram_manager<double, Degree, Domain>(
1230 varCount,
1231 nodePoolSize,
1232 overflowNodePoolSize,
1233 static_cast<std::vector<int32>&&>(order)
1234 )
1235{
1236}
1237
1238template<class Degree, class Domain>
1239reliability_manager<Degree, Domain>::reliability_manager(
1240 int32 const varCount,
1241 int64 const nodePoolSize,
1242 int64 const overflowNodePoolSize,
1243 domains::mixed domain,
1244 std::vector<int32> order
1245)
1246requires(domains::is_mixed<Domain>::value)
1247 :
1248 diagram_manager<double, Degree, Domain>(
1249 varCount,
1250 nodePoolSize,
1251 overflowNodePoolSize,
1252 static_cast<domains::mixed&&>(domain),
1253 static_cast<std::vector<int32>&&>(order)
1254 )
1255{
1256}
1257} // namespace teddy
1258
1259#endif
Base class for all diagram managers that generically implements all of the algorithms.
Definition diagram_manager.hpp:91
Cheap wrapper for the internal diagram node type.
Definition diagram.hpp:20
auto unsafe_get_root() const -> node_t *
Returns pointer to internal node type. You should probably don't use this one unless you know what yo...
Definition diagram.hpp:178
Definition node.hpp:91
Wraps prob. vector so that it can be used as matrix.
Definition probabilities.hpp:52
Base class for reliability managers.
Definition reliability_manager.hpp:43
auto mpvs_g(diagram_t const &diagram, int32 state, Out out) -> void
Finds all Minimal Path Vector (MPVs) of the system with respect to the system state state.
Definition reliability_manager.hpp:1055
auto mcvs_g(diagram_t const &diagram, int32 state, Out out) -> void
Finds all Minimal Cut Vector of the system with respect to the system state state.
Definition reliability_manager.hpp:1028
auto calculate_availability(Ps const &probs, diagram_t const &diagram) -> utils::second_t< Foo, double >
Calculates and returns availability of a BSS.
Definition reliability_manager.hpp:594
auto mcvs(diagram_t const &diagram, int32 state) -> std::vector< Vars >
Finds all Minimal Cut Vector (MCVs) of the system with respect to the system state State.
Definition reliability_manager.hpp:1004
auto fussell_vesely_importance(Ps const &probs, diagram_t const &dpld, double unavailability, int32 componentState, int32 componentIndex) -> double
Calculates Fussell-Vesely importance (FVI) of a component.
Definition reliability_manager.hpp:983
auto calculate_unavailability(Ps const &probs, diagram_t const &diagram) -> utils::second_t< Foo, double >
Calculates and returns unavailability of a BSS.
Definition reliability_manager.hpp:658
auto birnbaum_importance(Ps const &probs, diagram_t const &dpld) -> double
Calculates Birnbaum importance (BI) of a component.
Definition reliability_manager.hpp:973
auto calculate_unavailability(int32 state, Ps const &probs, diagram_t const &diagram) -> double
Calculates and returns system availability with respect to the system state state.
Definition reliability_manager.hpp:668
auto get_availability() const -> utils::second_t< Foo, double >
Returns availability of a BSS.
Definition reliability_manager.hpp:631
auto get_probability(int32 state) const -> double
Returns probability of given system state.
Definition reliability_manager.hpp:584
auto calculate_probabilities(Ps const &probs, diagram_t const &diagram) -> void
Calculates probabilities of all system states.
auto mpvs(diagram_t const &diagram, int32 state) -> std::vector< Vars >
Finds all Minimal Path Vector (MPVs) of the system with respect to the system state state.
Definition reliability_manager.hpp:1016
auto dpld(var_change varChange, FChange fChange, diagram_t const &diagram) -> diagram_t
Calculates Direct Partial Boolean Derivative.
Definition reliability_manager.hpp:783
auto calculate_probabilities(Ps const &probs, diagram_t const &diagram) -> void
Calculates probabilities of system states 0 and 1.
Definition reliability_manager.hpp:535
auto to_dpld_e(int32 varFrom, int32 varIndex, diagram_t const &dpld) -> diagram_t
Transforms dpld into Extended DPLD.
Definition reliability_manager.hpp:871
auto get_unavailability() -> utils::second_t< Foo, double >
Returns system unavailability of a BSS.
Definition reliability_manager.hpp:691
auto get_availability(int32 state) const -> double
Returns system availability with respect to the system state state.
Definition reliability_manager.hpp:639
auto state_frequency(diagram_t const &diagram, int32 state) -> double
Returns system state frequency of state state.
Definition reliability_manager.hpp:769
auto get_unavailability(int32 state) -> double
Returns system unavailability with respect to the system state state.
Definition reliability_manager.hpp:698
auto calculate_probability(Ps const &probs, diagram_t const &diagram) -> double
Calculates and returns probability of system state 1.
Definition reliability_manager.hpp:559
auto calculate_probability(int32 state, Ps const &probs, diagram_t const &diagram) -> double
Calculates and returns probability of a system state state.
Definition reliability_manager.hpp:573
auto calculate_availability(int32 state, Ps const &probs, diagram_t const &diagram) -> double
Calculates and returns system availability with respect to the system state state.
Definition reliability_manager.hpp:608
auto structural_importance(diagram_t const &dpld) -> double
Calculates Structural Importace (SI) of a component.
Definition reliability_manager.hpp:960
Definition reliability_manager.hpp:20
Definition node_manager.hpp:57
Definition node_manager.hpp:69
Definition node_manager.hpp:25
Describes change in a value of a variable.
Definition reliability_manager.hpp:28