open util/ternary
  open util/ordering[Atom] as A

  sig Atom {edges: Int -> Atom}

  one sig A,B,C,D,E,F,G,H,I,J
    extends Atom {}

  -- For efficiency: define ordering on nodes to make div unnecessary
  fun weight[g: Atom -> Int -> Atom]: Int {
    -- Assume: no self-loops
    -- Note .*A/next will overflow at 6 int
    sum a: Atom | sum b: a.^A/next | a.g.b
  }

  -- For efficiency: FIX A WEIGHTED GRAPH
  -- For efficiency: Turn on "infer partial instance" + define plainly
  fact fixed {
    edges =
      A->4->D + D->5->I + A->6->B + B->4->C + A->3->C +
      B->3->E + C->5->D + C->2->E + E->6->F + E->5->G +
      D->2->H + D->3->F + F->4->G + F->2->H + H->2->I +
      G->3->J + H->5->J + I->4->J +
      D->4->A + I->5->D + B->6->A + C->4->B + C->3->A +
      E->3->B + D->5->C + E->2->C + F->6->E + G->5->E +
      H->2->D + F->3->D + G->4->F + H->2->F + I->2->H +
      J->3->G + J->5->H + J->4->I
  }

  pred isUndirectedTree[r: Atom -> Atom] {
  	-- FILL
  }

  pred spans[graph1, graph2: Atom -> Atom] {
  	-- FILL
  }

  pred spanningTree[tree, graph2: Atom -> Atom] {
    spans[tree, graph2]
    isUndirectedTree[tree]
  }
  run spanningTree for exactly 5 Atom, 8 int

  pred properWeights[g: Atom -> Int -> Atom] {
    -- one weight per edge and weights within [1, 10]
    all a1, a2: Atom | lone i: Int | a1->i->a2 in g
    all i : Atom.g.Atom | i > 0 and i < 11
    -- symmetric weights
    all a1, a2: Atom | a1.g.a2 = a2.g.a1

  }

  pred minSpanningTree[tree, wgraph: Atom -> Int -> Atom] {
    spanningTree[select13[tree], select13[wgraph]]
    properWeights[wgraph]
    -- need to specify this because spans version won't look at weights
    tree in wgraph

    all tree2: Atom -> Int -> Atom | {
      (spanningTree[select13[tree2], select13[wgraph]] and
      tree2 in wgraph) implies
       weight[tree2] >= weight[tree]
    }
  }
  run minSpanningTree for exactly 4 Atom, 8 int

  run bigger {
    some tree: Atom -> Int -> Atom | {
      minSpanningTree[tree, edges]
    }
  } for exactly 10 Atom, 6 int