code: def _encode_penman(self, g, top=None):
          if top is None:
              top = g.top
          remaining = set(g.triples())
          variables = g.variables()
          store = defaultdict(lambda: ([], []))
          for t in g.triples():
              if t.inverted:
                  store[t.target][0].append(t)
                  store[t.source][1].append(Triple(*t, inverted=False))
              else:
                  store[t.source][0].append(t)
                  store[t.target][1].append(Triple(*t, inverted=True))
          p = defaultdict(list)
          topolist = [top]
          def _update(t):
              src, tgt = (t[2], t[0]) if t.inverted else (t[0], t[2])
              p[src].append(t)
              remaining.remove(t)
              if tgt in variables and t.relation != self.TYPE_REL:
                  topolist.append(tgt)
                  return tgt
              return None
          def _explore_preferred(src):
              ts = store.get(src, ([], []))[0]
              for t in ts:
                  if t in remaining:
                      tgt = _update(t)
                      if tgt is not None:
                          _explore_preferred(tgt)
              ts[:] = []
          _explore_preferred(top)
          while remaining:
              flip_candidates = [store.get(v, ([],[]))[1] for v in topolist]
              for fc in flip_candidates:
                  fc[:] = [c for c in fc if c in remaining]
              if not any(len(fc) > 0 for fc in flip_candidates):
                  raise EncodeError('Invalid graph; possibly disconnected.')
              c = next(c for fc in flip_candidates for c in fc)
              tgt = _update(c)
              if tgt is not None:
                  _explore_preferred(tgt)
          return self._layout(p, top, 0, set())