Force PyDelphin to return every Synopsis?

Is there a way to force the semi.find_synopsis function to find every possible synopsis for a predicate label?

Currently, I’m trying to generate something like “the north wall” and there are two possible synopses for “wall”:

It’s returning the first one, which causes me to have an MRS like this after my composition:

[ TOP: h41
  INDEX: e38
  RELS: < [ unknown LBL: h40 ARG: x20 ARG0: e38 ]
          [ _the_q LBL: h37 ARG0: x20 RSTR: h35 BODY: h36 ]
          [ compound LBL: h22 ARG0: e30 ARG1: x20 ARG2: x23 ]
          [ udef_q LBL: h29 ARG0: x23 RSTR: h27 BODY: h28 ]
          [ _north_n_of LBL: h25 ARG0: x23 ARG1: i24 ]
          [ _wall_n_of LBL: h22 ARG0: x20 ARG1: i21 ] >
  HCONS: < h27 qeq h25 h35 qeq h22 h41 qeq h40 > ]

But this generates 0 results, and when comparing to a parse of “the north wall” in the delphin-viz demo, the only difference is that the _wall_n_of predicate doesn’t have the extra ARG1. (I also don’t really understand why it can’t generate it anyway with the ARG1 not identified with anything, but regardless, it doesn’t seem to).

So I need to either:

  1. Only return the second synopsis (I couldn’t figure this out, I tried telling it args=x but I think maybe the first synopsis subsumes this so it doesn’t work the way I’m hoping? Not sure.
  2. Get every synopsis back and just try generating from more than multiple MRSs.

Right now Option 2 seems like the best fit for my project, but I would like to know how to do both of these things if possible.

The delphin.semi module doesn’t get that much attention so I’m not surprised to see a feature gap. I’m also happy to see the module being used :slight_smile:

By design, the SemI.find_synopsis() method returns one synopsis, so there isn’t a way to get it to return more than one.

You’ve shown how the args argument is not sufficient for selecting a particular synopsis. When args is used, it returns the first synopsis that subsumes args, and unmentioned roles are taken to mean “unconstrained”, thus args="x" or args={"ARG0": "x"} will also match args="xi" or args={"ARG0": "x", "ARG1": None}. The docs say this for delphin.semi.Synopsis.subsumes():

[…] the sequence or mapping must be a subset of the roles of the synopsis, and any missing must be optional roles, otherwise the synopsis does not subsume args.

In your case, this functionality is working against you, and there is no way to get that second synopsis using SemI.find_synopsis(). What you need is something like smi.find_synopsis(pred, args="x", complete=True), meaning that the argument description is complete and any unmentioned roles will fail to match.

I would put the logic in the Synopsis.subsumes() function around here:

like this:

    def subsumes(self, args, variables=None, complete=False):
        if len(args) > len(self):
            return False  # some arg won't be in the synopsis
        if complete and len(self) > len(args):
            return False  # args don't completely cover the synopsis

Then in SemI.find_synopsis() at these lines:

Change them like this:

    def find_synopsis(self, predicate, args=None, complete=False):
        for synopsis in self.predicates[predicate]:
            if not args or synopsis.subsumes(args, self.variables, complete=complete):

If this works for you, I’d be happy to review a pull request to effect that change in PyDelphin for the next version.

You can look at SemI.predicates[pred] for the list of synopses and create the appropriate search logic, perhaps modeled on Synopsis.subsumes(), so you don’t have to generate from each, assuming you know what kind of synopsis you want to begin with.