void
NBTrafficLightLogicCont::computeLogics(NBEdgeCont &ec, OptionsCont &oc) throw() {
    unsigned int no = 0;
    for (DefinitionContType::iterator i=myDefinitions.begin(); i!=myDefinitions.end(); i++) {
        std::string id = (*i).first;
        if (myComputed.find(id)!=myComputed.end()) {
            WRITE_WARNING("Traffic light '" + id + "' was already built.");
            continue;
        }
        // build program
        NBTrafficLightDefinition *def = (*i).second;
        NBTrafficLightLogic *built = def->compute(ec, oc);
        if (built==0) {
            WRITE_WARNING("Could not build traffic lights '" + id + "'");
            continue;
        }
        // compute offset
        SUMOTime T = built->getDuration();
        if (find(myHalfOffsetTLS.begin(), myHalfOffsetTLS.end(), id)!=myHalfOffsetTLS.end()) {
            built->setOffset((SUMOTime)(T/2.));
        }
        if (find(myQuarterOffsetTLS.begin(), myQuarterOffsetTLS.end(), id)!=myQuarterOffsetTLS.end()) {
            built->setOffset((SUMOTime)(T/4.));
        }
        // and insert the result after computation
        myComputed[(*i).first] = built;
        no++;
    }
    WRITE_MESSAGE(toString<int>(no) + " traffic light(s) computed.");
}
bool
NBTrafficLightLogicCont::computeSingleLogic(OptionsCont& oc, NBTrafficLightDefinition* def) {
    const std::string& id = def->getID();
    const std::string& programID = def->getProgramID();
    // build program
    NBTrafficLightLogic* built = def->compute(oc);
    if (built == 0) {
        WRITE_WARNING("Could not build program '" + programID + "' for traffic light '" + id + "'");
        return false;
    }
    // compute offset
    SUMOTime T = built->getDuration();
    if (myHalfOffsetTLS.count(id)) {
        built->setOffset((SUMOTime)(T / 2.));
    }
    if (myQuarterOffsetTLS.count(id)) {
        built->setOffset((SUMOTime)(T / 4.));
    }
    // and insert the result after computation
    // make sure we don't leak memory if computeSingleLogic is called externally
    if (myComputed[id][programID] != 0) {
        delete myComputed[id][programID];
    }
    myComputed[id][programID] = built;
    return true;
}
示例#3
0
/* Test the method 'getDuration'*/
TEST(NBTrafficLightLogic, test_method_getDuration) {	
	NBTrafficLightLogic *edge = new NBTrafficLightLogic("1","11",2);
	EXPECT_EQ(0, edge->getDuration());

	edge->addStep(3,"gr");
	edge->addStep(5,"rG");
	EXPECT_EQ(8, edge->getDuration());
	
}
示例#4
0
NBTrafficLightLogic*
NBLoadedTLDef::myCompute(const NBEdgeCont& ec, unsigned int brakingTime) {
    MsgHandler::getWarningInstance()->clear(); // !!!
    NBLoadedTLDef::SignalGroupCont::const_iterator i;
    // compute the switching times
    std::set<SUMOReal> tmpSwitchTimes;
    for (i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
        NBLoadedTLDef::SignalGroup* group = (*i).second;
        // needed later
        group->sortPhases();
        // patch the yellow time for this group
        group->patchTYellow(brakingTime, OptionsCont::getOptions().getBool("tls.yellow.patch-small"));
        // copy the now valid times into the container
        //  both the given red and green phases are added and also the
        //  yellow times
        std::vector<SUMOReal> gtimes = group->getTimes(myCycleDuration);
        for (std::vector<SUMOReal>::const_iterator k = gtimes.begin(); k != gtimes.end(); k++) {
            tmpSwitchTimes.insert(*k);
        }
    }
    std::vector<SUMOReal> switchTimes;
    copy(tmpSwitchTimes.begin(), tmpSwitchTimes.end(), back_inserter(switchTimes));
    sort(switchTimes.begin(), switchTimes.end());

    // count the signals
    unsigned int noSignals = 0;
    for (i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
        noSignals += (*i).second->getLinkNo();
    }
    // build the phases
    NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noSignals, myOffset, myType);
    for (std::vector<SUMOReal>::iterator l = switchTimes.begin(); l != switchTimes.end(); l++) {
        // compute the duration of the current phase
        unsigned int duration;
        if (l != switchTimes.end() - 1) {
            // get from the difference to the next switching time
            duration = (unsigned int)((*(l + 1)) - (*l));
        } else {
            // get from the differenc to the first switching time
            duration = (unsigned int)(myCycleDuration - (*l) + * (switchTimes.begin()));
        }
        // no information about yellow times will be generated
        assert((*l) >= 0);
        logic->addStep(TIME2STEPS(duration), buildPhaseState(ec, (unsigned int)(*l)));
    }
    // check whether any warnings were printed
    if (MsgHandler::getWarningInstance()->wasInformed()) {
        WRITE_WARNING("During computation of traffic light '" + getID() + "'.");
    }
    logic->closeBuilding();
    return logic;
}
示例#5
0
void
NBLoadedSUMOTLDef::removeConnection(const NBConnection& conn, bool reconstruct) {
    NBConnectionVector::iterator it = myControlledLinks.begin();
    // find the connection but ignore its TLIndex since it might have been
    // invalidated by an earlier removal
    for (; it != myControlledLinks.end(); ++it) {
        if (it->getFrom() == conn.getFrom() &&
                it->getTo() == conn.getTo() &&
                it->getFromLane() == conn.getFromLane() &&
                it->getToLane() == conn.getToLane()) {
            break;
        }
    }
    if (it == myControlledLinks.end()) {
        // a traffic light doesn't always controll all connections at a junction
        // especially when using the option --tls.join
        return;
    }
    const int removed = it->getTLIndex();
    // remove the connection
    myControlledLinks.erase(it);
    if (reconstruct) {
        // updating the edge is only needed for immediate use in NETEDIT.
        // It may conflict with loading diffs
        conn.getFrom()->setControllingTLInformation(conn, "");
        // shift link numbers down so there is no gap
        for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
            NBConnection& c = *it;
            if (c.getTLIndex() > removed) {
                c.setTLIndex(c.getTLIndex() - 1);
            }
        }
        // update controlling information with new link numbers
        setTLControllingInformation();
        // rebuild the logic
        const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
        NBTrafficLightLogic* newLogic = new NBTrafficLightLogic(getID(), getProgramID(), 0, myOffset, myType);
        for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
            std::string newState = it->state;
            newState.erase(newState.begin() + removed);
            newLogic->addStep(it->duration, newState);
        }
        delete myTLLogic;
        myTLLogic = newLogic;
    }
}
NBTrafficLightLogic*
NBTrafficLightDefinition::compute(OptionsCont& oc) {
    // it is not really a traffic light if no incoming edge exists
    if (amInvalid()) {
        // make a copy of myControlledNodes because it will be modified;
        std::vector<NBNode*> nodes = myControlledNodes;
        for (std::vector<NBNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
            (*it)->removeTrafficLight(this);
        }
        WRITE_WARNING("The traffic light '" + getID() + "' does not control any links; it will not be build.");
        return 0;
    }
    // compute the time needed to brake
    unsigned int brakingTime = computeBrakingTime(oc.getFloat("tls.yellow.min-decel"));
    // perform the computation depending on whether the traffic light
    //  definition was loaded or shall be computed new completely
    if (oc.isSet("tls.yellow.time")) {
        brakingTime = oc.getInt("tls.yellow.time");
    }
    NBTrafficLightLogic* ret = myCompute(brakingTime);
    ret->addParameter(getMap());
    return ret;
}
示例#7
0
NBTrafficLightLogic*
NBLoadedTLDef::myCompute(unsigned int brakingTimeSeconds) {
    MsgHandler::getWarningInstance()->clear(); // !!!
    NBLoadedTLDef::SignalGroupCont::const_iterator i;
    // compute the switching times
    std::set<SUMOReal> tmpSwitchTimes;
    for (i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
        NBLoadedTLDef::SignalGroup* group = (*i).second;
        // needed later
        group->sortPhases();
        // patch the yellow time for this group
        group->patchTYellow(brakingTimeSeconds, OptionsCont::getOptions().getBool("tls.yellow.patch-small"));
        // copy the now valid times into the container
        //  both the given red and green phases are added and also the
        //  yellow times
        std::vector<SUMOReal> gtimes = group->getTimes(myCycleDuration);
        for (std::vector<SUMOReal>::const_iterator k = gtimes.begin(); k != gtimes.end(); k++) {
            tmpSwitchTimes.insert(*k);
        }
    }
    std::vector<SUMOReal> switchTimes;
    copy(tmpSwitchTimes.begin(), tmpSwitchTimes.end(), back_inserter(switchTimes));
    sort(switchTimes.begin(), switchTimes.end());

    // count the signals
    unsigned int noSignals = 0;
    for (i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
        noSignals += (*i).second->getLinkNo();
    }
    // build the phases
    NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noSignals, myOffset, myType);
    for (std::vector<SUMOReal>::iterator l = switchTimes.begin(); l != switchTimes.end(); l++) {
        // compute the duration of the current phase
        unsigned int duration;
        if (l != switchTimes.end() - 1) {
            // get from the difference to the next switching time
            duration = (unsigned int)((*(l + 1)) - (*l));
        } else {
            // get from the differenc to the first switching time
            duration = (unsigned int)(myCycleDuration - (*l) + * (switchTimes.begin()));
        }
        // no information about yellow times will be generated
        assert((*l) >= 0);
        logic->addStep(TIME2STEPS(duration), buildPhaseState((unsigned int)(*l)));
    }
    // check whether any warnings were printed
    if (MsgHandler::getWarningInstance()->wasInformed()) {
        WRITE_WARNING("During computation of traffic light '" + getID() + "'.");
    }
    logic->closeBuilding();

    // initialize myNeedsContRelation
    myNeedsContRelation.clear();
    const bool controlledWithin = !OptionsCont::getOptions().getBool("tls.uncontrolled-within");
    const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = logic->getPhases();
    for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
        const std::string state = (*it).state;
        for (NBConnectionVector::const_iterator it1 = myControlledLinks.begin(); it1 != myControlledLinks.end(); it1++) {
            const NBConnection& c1 = *it1;
            const int i1 = c1.getTLIndex();
            if (i1 == NBConnection::InvalidTlIndex || state[i1] != 'g' || c1.getFrom() == 0 || c1.getTo() == 0) {
                continue;
            }
            for (NBConnectionVector::const_iterator it2 = myControlledLinks.begin(); it2 != myControlledLinks.end(); it2++) {
                const NBConnection& c2 = *it2;
                const int i2 = c2.getTLIndex();
                if (i2 != NBConnection::InvalidTlIndex
                        && i2 != i1
                        && (state[i2] == 'G' || state[i2] == 'g')
                        && c2.getFrom() != 0 && c2.getTo() != 0) {
                    const bool rightTurnConflict = NBNode::rightTurnConflict(
                                                       c1.getFrom(), c1.getTo(), c1.getFromLane(), c2.getFrom(), c2.getTo(), c2.getFromLane());
                    if (forbids(c2.getFrom(), c2.getTo(), c1.getFrom(), c1.getTo(), true, controlledWithin) || rightTurnConflict) {
                        myNeedsContRelation.insert(StreamPair(c1.getFrom(), c1.getTo(), c2.getFrom(), c2.getTo()));
                    }
                }
            }
        }
    }
    myNeedsContRelationReady = true;

    return logic;
}
示例#8
0
文件: NBOwnTLDef.cpp 项目: harora/ITS
NBTrafficLightLogic*
NBOwnTLDef::myCompute(const NBEdgeCont&,
                      unsigned int brakingTimeSeconds) {
    const SUMOTime brakingTime = TIME2STEPS(brakingTimeSeconds);
    const SUMOTime leftTurnTime = TIME2STEPS(6); // make configurable ?
    // build complete lists first
    const EdgeVector& incoming = getIncomingEdges();
    EdgeVector fromEdges, toEdges;
    std::vector<bool> isLeftMoverV, isTurnaround;
    unsigned int noLanesAll = 0;
    unsigned int noLinksAll = 0;
    for (unsigned int i1 = 0; i1 < incoming.size(); i1++) {
        unsigned int noLanes = incoming[i1]->getNumLanes();
        noLanesAll += noLanes;
        for (unsigned int i2 = 0; i2 < noLanes; i2++) {
            NBEdge* fromEdge = incoming[i1];
            std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2);
            noLinksAll += (unsigned int) approached.size();
            for (unsigned int i3 = 0; i3 < approached.size(); i3++) {
                if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
                    --noLinksAll;
                    continue;
                }
                assert(i3 < approached.size());
                NBEdge* toEdge = approached[i3].toEdge;
                fromEdges.push_back(fromEdge);
                //myFromLanes.push_back(i2);
                toEdges.push_back(toEdge);
                if (toEdge != 0) {
                    isLeftMoverV.push_back(
                        isLeftMover(fromEdge, toEdge)
                        ||
                        fromEdge->isTurningDirectionAt(fromEdge->getToNode(), toEdge));

                    isTurnaround.push_back(
                        fromEdge->isTurningDirectionAt(
                            fromEdge->getToNode(), toEdge));
                } else {
                    isLeftMoverV.push_back(true);
                    isTurnaround.push_back(true);
                }
            }
        }
    }

    NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noLinksAll, myOffset, myType);
    EdgeVector toProc = incoming;
    const SUMOTime greenTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.green.time"));
    // build all phases
    while (toProc.size() > 0) {
        std::pair<NBEdge*, NBEdge*> chosen;
        if (incoming.size() == 2) {
            chosen = std::pair<NBEdge*, NBEdge*>(toProc[0], static_cast<NBEdge*>(0));
            toProc.erase(toProc.begin());
        } else {
            chosen = getBestPair(toProc);
        }
        unsigned int pos = 0;
        std::string state((size_t) noLinksAll, 'o');
        // plain straight movers
        for (unsigned int i1 = 0; i1 < (unsigned int) incoming.size(); ++i1) {
            NBEdge* fromEdge = incoming[i1];
            const bool inChosen = fromEdge == chosen.first || fromEdge == chosen.second; //chosen.find(fromEdge)!=chosen.end();
            const unsigned int numLanes = fromEdge->getNumLanes();
            for (unsigned int i2 = 0; i2 < numLanes; i2++) {
                std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2);
                for (unsigned int i3 = 0; i3 < approached.size(); ++i3) {
                    if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
                        continue;
                    }
                    if (inChosen) {
                        state[pos] = 'G';
                    } else {
                        state[pos] = 'r';
                    }
                    ++pos;
                }
            }
        }
        // correct behaviour for those that are not in chosen, but may drive, though
        for (unsigned int i1 = 0; i1 < pos; ++i1) {
            if (state[i1] == 'G') {
                continue;
            }
            bool isForbidden = false;
            for (unsigned int i2 = 0; i2 < pos && !isForbidden; ++i2) {
                if (state[i2] == 'G' && !isTurnaround[i2] &&
                        (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true) || forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) {
                    isForbidden = true;
                }
            }
            if (!isForbidden) {
                state[i1] = 'G';
            }
        }
        // correct behaviour for those that have to wait (mainly left-mover)
        bool haveForbiddenLeftMover = false;
        for (unsigned int i1 = 0; i1 < pos; ++i1) {
            if (state[i1] != 'G') {
                continue;
            }
            for (unsigned int i2 = 0; i2 < pos; ++i2) {
                if ((state[i2] == 'G' || state[i2] == 'g') && forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true)) {
                    state[i1] = 'g';
                    if (!isTurnaround[i1]) {
                        haveForbiddenLeftMover = true;
                    }
                }
            }
        }
        // add step
        logic->addStep(greenTime, state);

        if (brakingTime > 0) {
            // build yellow (straight)
            for (unsigned int i1 = 0; i1 < pos; ++i1) {
                if (state[i1] != 'G' && state[i1] != 'g') {
                    continue;
                }
                if ((state[i1] >= 'a' && state[i1] <= 'z') && haveForbiddenLeftMover) {
                    continue;
                }
                state[i1] = 'y';
            }
            // add step
            logic->addStep(brakingTime, state);
        }

        if (haveForbiddenLeftMover && !myHaveSinglePhase) {
            // build left green
            for (unsigned int i1 = 0; i1 < pos; ++i1) {
                if (state[i1] == 'Y' || state[i1] == 'y') {
                    state[i1] = 'r';
                    continue;
                }
                if (state[i1] == 'g') {
                    state[i1] = 'G';
                }
            }
            // add step
            logic->addStep(leftTurnTime, state);

            // build left yellow
            if (brakingTime > 0) {
                for (unsigned int i1 = 0; i1 < pos; ++i1) {
                    if (state[i1] != 'G' && state[i1] != 'g') {
                        continue;
                    }
                    state[i1] = 'y';
                }
                // add step
                logic->addStep(brakingTime, state);
            }
        }
    }
    const SUMOTime totalDuration = logic->getDuration();
    if (totalDuration > 0) {
        if (totalDuration > 3 * (greenTime + 2 * brakingTime + leftTurnTime)) {
            WRITE_WARNING("The traffic light '" + getID() + "' has a high cycle time of " + time2string(totalDuration) + ".");
        }
        return logic;
    } else {
        delete logic;
        return 0;
    }
}
示例#9
0
NBTrafficLightLogic *
NBOwnTLDef::myCompute(const NBEdgeCont &,
                      unsigned int brakingTime) throw() {
    // build complete lists first
    const EdgeVector &incoming = getIncomingEdges();
    std::vector<NBEdge*> fromEdges, toEdges;
    std::vector<bool> isLeftMoverV, isTurnaround;
    unsigned int noLanesAll = 0;
    unsigned int noLinksAll = 0;
    for (unsigned int i1=0; i1<incoming.size(); i1++) {
        unsigned int noLanes = incoming[i1]->getNoLanes();
        noLanesAll += noLanes;
        for (unsigned int i2=0; i2<noLanes; i2++) {
            NBEdge *fromEdge = incoming[i1];
            std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2);
            noLinksAll += (unsigned int) approached.size();
            for (unsigned int i3=0; i3<approached.size(); i3++) {
                if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
                    --noLinksAll;
                    continue;
                }
                assert(i3<approached.size());
                NBEdge *toEdge = approached[i3].toEdge;
                fromEdges.push_back(fromEdge);
                //myFromLanes.push_back(i2);
                toEdges.push_back(toEdge);
                if (toEdge!=0) {
                    isLeftMoverV.push_back(
                        isLeftMover(fromEdge, toEdge)
                        ||
                        fromEdge->isTurningDirectionAt(fromEdge->getToNode(), toEdge));

                    isTurnaround.push_back(
                        fromEdge->isTurningDirectionAt(
                            fromEdge->getToNode(), toEdge));
                } else {
                    isLeftMoverV.push_back(true);
                    isTurnaround.push_back(true);
                }
            }
        }
    }

    NBTrafficLightLogic *logic = new NBTrafficLightLogic(getID(), "0", noLinksAll);
    std::vector<NBEdge*> toProc = incoming;
    // build all phases
    while (toProc.size()>0) {
        std::pair<NBEdge*, NBEdge*> chosen;
        if (incoming.size()==2) {
            chosen = std::pair<NBEdge*, NBEdge*>(toProc[0], static_cast<NBEdge*>(0));
            toProc.erase(toProc.begin());
        } else {
            chosen = getBestPair(toProc);
        }
        unsigned int pos = 0;
        unsigned int duration = 31;
        if (OptionsCont::getOptions().isSet("traffic-light-green")) {
            duration = OptionsCont::getOptions().getInt("traffic-light-green");
        }
        std::string state((size_t) noLinksAll, 'o');
        // plain straight movers
        for (unsigned int i1=0; i1<(unsigned int) incoming.size(); ++i1) {
            NBEdge *fromEdge = incoming[i1];
            bool inChosen = fromEdge==chosen.first||fromEdge==chosen.second;//chosen.find(fromEdge)!=chosen.end();
            unsigned int noLanes = fromEdge->getNoLanes();
            for (unsigned int i2=0; i2<noLanes; i2++) {
                std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2);
                for (unsigned int i3=0; i3<approached.size(); ++i3) {
                    if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
                        continue;
                    }
                    if (inChosen) {
                        state[pos] = 'G';
                    } else {
                        state[pos] = 'r';
                    }
                    ++pos;
                }
            }
        }
        // correct behaviour for those that are not in chosen, but may drive, though
        for (unsigned int i1=0; i1<pos; ++i1) {
            if (state[i1]=='G') {
                continue;
            }
            bool isForbidden = false;
            for (unsigned int i2=0; i2<pos&&!isForbidden; ++i2) {
                if (state[i2]=='G'&&!isTurnaround[i2]&&
                        (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true)||forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) {
                    isForbidden = true;
                }
            }
            if (!isForbidden) {
                state[i1] = 'G';
            }
        }
        // correct behaviour for those that have to wait (mainly left-mover)
        bool haveForbiddenLeftMover = false;
        for (unsigned int i1=0; i1<pos; ++i1) {
            if (state[i1]!='G') {
                continue;
            }
            for (unsigned int i2=0; i2<pos; ++i2) {
                if ((state[i2]=='G'||state[i2]=='g')&&forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true)) {
                    state[i1] = 'g';
                    if (!isTurnaround[i1]) {
                        haveForbiddenLeftMover = true;
                    }
                }
            }
        }

        // add step
        logic->addStep(duration, state);

        if (brakingTime>0) {
            // build yellow (straight)
            duration = brakingTime;
            for (unsigned int i1=0; i1<pos; ++i1) {
                if (state[i1]!='G'&&state[i1]!='g') {
                    continue;
                }
                if ((state[i1]>='a'&&state[i1]<='z')&&haveForbiddenLeftMover) {
                    continue;
                }
                state[i1] = 'y';
            }
            // add step
            logic->addStep(duration, state);
        }

        if (haveForbiddenLeftMover) {
            // build left green
            duration = 6;
            for (unsigned int i1=0; i1<pos; ++i1) {
                if (state[i1]=='Y'||state[i1]=='y') {
                    state[i1] = 'r';
                    continue;
                }
                if (state[i1]=='g') {
                    state[i1] = 'G';
                }
            }
            // add step
            logic->addStep(duration, state);

            // build left yellow
            if (brakingTime>0) {
                duration = brakingTime;
                for (unsigned int i1=0; i1<pos; ++i1) {
                    if (state[i1]!='G'&&state[i1]!='g') {
                        continue;
                    }
                    state[i1] = 'y';
                }
                // add step
                logic->addStep(duration, state);
            }
        }
    }
    if (logic->getDuration()>0) {
        return logic;
    } else {
        delete logic;
        return 0;
    }

}