00001
00002
00003 #include "fsm.h"
00004 #include "optimizer.h"
00005
00006
00007 Optimizer::Optimizer(const Fsm& fsm, ostream* debug): fsm_(fsm), debug_(debug) {
00008 }
00009
00010 bool&
00011 Optimizer::distinct(const Fsm::State& q1, const Fsm::State& q2) {
00012
00013
00014 if (q1 < q2)
00015 return distinct_[make_pair(q2,q1)];
00016 else
00017 return distinct_[make_pair(q1,q2)];
00018 }
00019
00020 ref<Fsm>
00021 Optimizer::optimize() {
00022
00023
00024 if (!fsm_.is_deterministic())
00025 return ref<Fsm>();
00026
00027
00028
00029
00030 for (Fsm::STATES::const_iterator i= fsm_.sbegin(); i != fsm_.send(); ++i)
00031 for (Fsm::STATES::const_iterator j = fsm_.sbegin(); j!=i; ++j)
00032 distinct(*i,*j) = ( fsm_.is_final(*i) != fsm_.is_final(*j) );
00033
00034
00035
00036
00037 bool change(true);
00038
00039 while (change) {
00040 change = false;
00041 for (Fsm::STATES::const_iterator i = fsm_.sbegin(); i != fsm_.send(); ++i)
00042 for (Fsm::STATES::const_iterator j = fsm_.sbegin(); j!=i; ++j)
00043 if (distinct(*i,*j))
00044 ;
00045 else {
00046
00047 for (Fsm::SYMBOLS::const_iterator a = fsm_.abegin(); a!= fsm_.aend(); ++a) {
00048 Fsm::State qi(fsm_.ddelta(*i,*a));
00049 Fsm::State qj(fsm_.ddelta(*j,*a));
00050 if (distinct(qi,qj)) {
00051 distinct(*i,*j) = change = true;
00052 break;
00053 }
00054 }
00055 }
00056
00057 }
00058
00059 if (debug_) {
00060 for (Fsm::STATES::const_iterator i = fsm_.sbegin(); i != fsm_.send(); ++i)
00061 for (Fsm::STATES::const_iterator j = fsm_.sbegin(); j!=i; ++j)
00062 *debug_ << "distinct(" << *i << "," << *j << ") = "
00063 << ( distinct(*i,*j) ? "true" : "false" ) << "\n";
00064 }
00065
00066
00067
00068
00069
00070
00071 ref<Fsm> ofsm(Fsm::create(eq_class(fsm_.initial_state())));
00072
00073
00074
00075
00076 for (Fsm::STATES::const_iterator i = fsm_.fbegin(); i != fsm_.fend(); ++i)
00077 ofsm->add_final_state(eq_class(*i));
00078
00079
00080
00081
00082
00083 for (Fsm::STATES::const_iterator i = fsm_.sbegin(); i != fsm_.send(); ++i)
00084 for (Fsm::SYMBOLS::const_iterator a = fsm_.abegin(); a!= fsm_.aend(); ++a)
00085 ofsm->add_transition(eq_class(*i), *a, eq_class(fsm_.ddelta(*i,*a)));
00086
00087 return ofsm;
00088 }
00089
00090 Fsm::State
00091 Optimizer::eq_class(const Fsm::State& q) {
00092
00093
00094 Fsm::STATES e;
00095 e.insert(q);
00096
00097 for (Fsm::STATES::const_iterator i = fsm_.sbegin(); i != fsm_.send(); ++i)
00098 if ( (*i!=q) && (!distinct(*i,q)) )
00099 e.insert(*i);
00100
00101 if (debug_)
00102 *debug_ << "eq_class(" << q << ") = " << e << "\n";
00103
00104 return *e.begin();
00105 }