Пример #1
0
 def test_or(self):
     ast = negation_normal_form(parse_ctlq("AF ('admin = bob' | AG ?)"))
     self.assertTrue(check_ctlqx(ast))
     fsm = self.init_model()
     solution = {HashableDict({'admin': 'alice', 'state': 'waiting'}),
                 HashableDict({'admin': 'alice', 'state': 'processing'})}
     self.assertCountEqual(bdd_to_set(fsm, solve_ctlqx(fsm, ast)), solution)
Пример #2
0
    def test_bdd_to_set(self):
        set_ = {HashableDict({'state': 'ready', 'request': 'TRUE'}),
                HashableDict({'state': 'ready', 'request': 'FALSE'})}

        init_nusmv()
        fsm = self.init_model()
        self.assertEqual(bdd_to_set(fsm, fsm.init), set_)
        deinit_nusmv()
Пример #3
0
 def test_au(self):
     ast = negation_normal_form(parse_ctlq("A[? U 'state = processing']"))
     self.assertTrue(check_ctlqx(ast))
     fsm = self.init_model()
     solution = {HashableDict({'admin': 'none', 'state': 'starting'}),
                 HashableDict({'admin': 'none', 'state': 'choosing'}),
                 HashableDict({'admin': 'alice', 'state': 'waiting'}),
                 HashableDict({'admin': 'bob', 'state': 'waiting'})}
     self.assertCountEqual(bdd_to_set(fsm, solve_ctlqx(fsm, ast)), solution)
Пример #4
0
 def test_or(self):
     ast = negation_normal_form(parse_ctlq("AF ('admin = bob' | AG ?)"))
     self.assertTrue(check_ctlqx(ast))
     fsm = self.init_model()
     solution = {
         HashableDict({
             'admin': 'alice',
             'state': 'waiting'
         }),
         HashableDict({
             'admin': 'alice',
             'state': 'processing'
         })
     }
     self.assertCountEqual(bdd_to_set(fsm, solve_ctlqx(fsm, ast)), solution)
Пример #5
0
    def test_bdd_to_set(self):
        set_ = {
            HashableDict({
                'state': 'ready',
                'request': 'TRUE'
            }),
            HashableDict({
                'state': 'ready',
                'request': 'FALSE'
            })
        }

        init_nusmv()
        fsm = self.init_model()
        self.assertEqual(bdd_to_set(fsm, fsm.init), set_)
        deinit_nusmv()
Пример #6
0
 def test_au(self):
     ast = negation_normal_form(parse_ctlq("A[? U 'state = processing']"))
     self.assertTrue(check_ctlqx(ast))
     fsm = self.init_model()
     solution = {
         HashableDict({
             'admin': 'none',
             'state': 'starting'
         }),
         HashableDict({
             'admin': 'none',
             'state': 'choosing'
         }),
         HashableDict({
             'admin': 'alice',
             'state': 'waiting'
         }),
         HashableDict({
             'admin': 'bob',
             'state': 'waiting'
         })
     }
     self.assertCountEqual(bdd_to_set(fsm, solve_ctlqx(fsm, ast)), solution)
Пример #7
0
 def test_ax(self):
     ast = negation_normal_form(parse_ctlq("AX ?"))
     self.assertTrue(check_ctlqx(ast))
     fsm = self.init_model()
     solution = {HashableDict({'admin': 'none', 'state': 'choosing'})}
     self.assertCountEqual(bdd_to_set(fsm, solve_ctlqx(fsm, ast)), solution)
Пример #8
0
def cli(model_path, query, order):
    """Solve QUERY that belongs to fragment CTLQx for model in MODEL_PATH."""
    try:
        # Parse `query` and transform it in NNF.
        ast = negation_normal_form(parse_ctlq(query))

        # Check that `query` belongs to fragment CTLQx.
        if not check_ctlqx(ast):
            click.echo("Error: {query} does not belong to CTLQx".format(query=query))
            # Quit PyTLQ.
            sys.exit()

        # Initialize NuSMV.
        with init_nusmv():
            # Load model from `model_path`.
            load(model_path)
            # Enable dynamic reordering of the variables.
            enable_dynamic_reordering()
            # Check if an order file is given.
            if order:
                # Build model with pre-calculated variable ordering.
                compute_model(variables_ordering=order)
            else:
                # Build model.
                compute_model()
            # Retrieve FSM of the model.
            fsm = prop_database().master.bddFsm

            # Solve `query` in `fsm`.
            solution = solve_ctlqx(fsm, ast)

            # Display solution.
            click.echo("Solution states:")
            if not solution:
                click.echo("No solution")
                # Quit PyTLQ.
                sys.exit()
            elif solution.is_false():
                click.echo("False")
                # Quit PyTLQ.
                sys.exit()
            else:
                size = fsm.count_states(solution)
                if size > 100:
                    if click.confirm(
                        "The number of states is too large"
                        " ({size}). Do you still want to print"
                        " them?".format(size=size)
                    ):
                        pprint(bdd_to_set(fsm, solution))
                else:
                    pprint(bdd_to_set(fsm, solution))

            # Ask for further manipulations.
            while True:
                command = click.prompt(
                    "\nWhat do you want to do?"
                    "\n  1. Project the solution on a"
                    " subset of the variables"
                    "\n  2. Simplify the solution according"
                    " to Chan's approximate conjunctive"
                    " decomposition"
                    "\n  3. Quit PyTLQ"
                    "\nYour choice",
                    type=click.IntRange(1, 3),
                    default=3,
                )

                # Check if solution must be projected or simplified.
                if command == 1 or command == 2:

                    # Gather more information.
                    click.echo("")
                    if command == 2:
                        maximum = click.prompt(
                            "Please enter the maximum"
                            " number of variables that must"
                            " appear in the conjuncts of"
                            " the simplification",
                            type=int,
                            default=1,
                        )
                    variables = click.prompt(
                        "Please enter the list of" " variables of interest," " separated by commas",
                        type=str,
                        default="all the variables",
                    )
                    # Format `variables`.
                    if variables == "all the variables":
                        variables = None
                    else:
                        variables = variables.replace(" ", "").split(",")

                    if command == 1:
                        # Project solution and display projection.
                        click.echo("\nProjection:")
                        click.echo(project(fsm, solution, variables))
                    else:
                        # Simplify solution and display simplification.
                        click.echo("\nApproximate conjunctive decomposition:")
                        click.echo(simplify(fsm, solution, maximum, variables))

                # No further manipulations are needed.
                else:
                    break

    except Exception as error:
        click.echo("Error: {msg}".format(msg=error))
Пример #9
0
def cli(model_path, query, order):
    """Solve QUERY that belongs to fragment CTLQx for model in MODEL_PATH."""
    try:
        # Parse `query` and transform it in NNF.
        ast = negation_normal_form(parse_ctlq(query))

        # Check that `query` belongs to fragment CTLQx.
        if not check_ctlqx(ast):
            click.echo('Error: {query} does not belong to CTLQx'
                       .format(query=query))
            # Quit PyTLQ.
            sys.exit()

        # Initialize NuSMV.
        with init_nusmv():
            # Load model from `model_path`.
            load(model_path)
            # Enable dynamic reordering of the variables.
            enable_dynamic_reordering()
            # Check if an order file is given.
            if order:
                # Build model with pre-calculated variable ordering.
                compute_model(variables_ordering=order)
            else:
                # Build model.
                compute_model()
            # Retrieve FSM of the model.
            fsm = prop_database().master.bddFsm

            # Solve `query` in `fsm`.
            solution = solve_ctlqx(fsm, ast)

            # Display solution.
            click.echo('Solution states:')
            if not solution:
                click.echo('No solution')
                # Quit PyTLQ.
                sys.exit()
            elif solution.is_false():
                click.echo('False')
                # Quit PyTLQ.
                sys.exit()
            else:
                size = fsm.count_states(solution)
                if size > 100:
                    if click.confirm('The number of states is too large'
                                     ' ({size}). Do you still want to print'
                                     ' them?'.format(size=size)):
                        pprint(bdd_to_set(fsm, solution))
                else:
                    pprint(bdd_to_set(fsm, solution))

            # Ask for further manipulations.
            while True:
                command = click.prompt('\nWhat do you want to do?'
                                       '\n  1. Project the solution on a'
                                       ' subset of the variables'
                                       '\n  2. Simplify the solution according'
                                       ' to Chan\'s approximate conjunctive'
                                       ' decomposition'
                                       '\n  3. Quit PyTLQ'
                                       '\nYour choice',
                                       type=click.IntRange(1, 3), default=3)

                # Check if solution must be projected or simplified.
                if command == 1 or command == 2:

                    # Gather more information.
                    click.echo('')
                    if command == 2:
                        maximum = click.prompt('Please enter the maximum'
                                               ' number of variables that must'
                                               ' appear in the conjuncts of'
                                               ' the simplification', type=int,
                                               default=1)
                    variables = click.prompt('Please enter the list of'
                                             ' variables of interest,'
                                             ' separated by commas', type=str,
                                             default='all the variables')
                    # Format `variables`.
                    if variables == 'all the variables':
                        variables = None
                    else:
                        variables = variables.replace(" ", "").split(',')

                    if command == 1:
                        # Project solution and display projection.
                        click.echo('\nProjection:')
                        click.echo(project(fsm, solution, variables))
                    else:
                        # Simplify solution and display simplification.
                        click.echo('\nApproximate conjunctive decomposition:')
                        click.echo(simplify(fsm, solution, maximum, variables))

                # No further manipulations are needed.
                else:
                    break

    except Exception as error:
        click.echo('Error: {msg}'.format(msg=error))
Пример #10
0
 def test_ax(self):
     ast = negation_normal_form(parse_ctlq("AX ?"))
     self.assertTrue(check_ctlqx(ast))
     fsm = self.init_model()
     solution = {HashableDict({'admin': 'none', 'state': 'choosing'})}
     self.assertCountEqual(bdd_to_set(fsm, solve_ctlqx(fsm, ast)), solution)