func (s *solution) solveWithHint(vID int, h compiled.Hint) error {
	inputs := make([]fr.Element, len(h.Inputs))
	for i := 0; i < len(h.Inputs); i++ {
		for j := 0; j < len(h.Inputs[i]); j++ {
			ciID, viID, visibility := h.Inputs[i][j].Unpack()
			if visibility == compiled.Virtual {
				inputs[i].Add(&inputs[i], &s.coefficients[ciID])
				continue
			}
			if !s.solved[viID] {
				return errors.New("expected wire to be instantiated while evaluating hint")
			}
			v := s.computeTerm(h.Inputs[i][j])
			inputs[i].Add(&inputs[i], &v)
		}
	}
	f, ok := s.mHintsFunctions[h.ID]
	if !ok {
		return errors.New("missing hint function")
	}
	v, err := f(inputs)
	if err != nil {
		return err
	}
	s.set(vID, v)
	return nil
}
solveHint compute solution.values[vID] using provided solver hint
package cs
import (
	"errors"
	"fmt"
	"io"
	"github.com/consensys/gnark/backend/hint"
	"github.com/consensys/gnark/internal/backend/compiled"
	"github.com/consensys/gnark-crypto/ecc/bn254/fr"
)
var ErrUnsatisfiedConstraint = errors.New("constraint is not satisfied")
type solution struct {
	values, coefficients []fr.Element
	solved               []bool
	nbSolved             int
	mHintsFunctions      map[hint.ID]hintFunction
}
func newSolution(nbWires int, hintFunctions []hint.Function, coefficients []fr.Element) (solution, error) {
	s := solution{
		values:          make([]fr.Element, nbWires),
		coefficients:    coefficients,
		solved:          make([]bool, nbWires),
		mHintsFunctions: make(map[hint.ID]hintFunction, len(hintFunctions)+2),
	}
	s.mHintsFunctions = make(map[hint.ID]hintFunction, len(hintFunctions)+2)
	s.mHintsFunctions[hint.IsZero] = powModulusMinusOne
	s.mHintsFunctions[hint.IthBit] = ithBit
	for i := 0; i < len(hintFunctions); i++ {
		if _, ok := s.mHintsFunctions[hintFunctions[i].ID]; ok {
			return solution{}, fmt.Errorf("duplicate hint function with id %d", uint32(hintFunctions[i].ID))
		}
		f, ok := hintFunctions[i].F.(hintFunction)
		if !ok {
			return solution{}, fmt.Errorf("invalid hint function signature with id %d", uint32(hintFunctions[i].ID))
		}
		s.mHintsFunctions[hintFunctions[i].ID] = f
	}
	return s, nil
}
func (s *solution) set(id int, value fr.Element) {
	if s.solved[id] {
		panic("solving the same wire twice should never happen.")
	}
	s.values[id] = value
	s.solved[id] = true
	s.nbSolved++
}
func (s *solution) isValid() bool {
	return s.nbSolved == len(s.values)
}
func (s *solution) computeTerm(t compiled.Term) fr.Element {
	cID, vID, _ := t.Unpack()
	if cID != 0 && !s.solved[vID] {
		panic("computing a term with an unsolved wire")
	}
	switch cID {
	case compiled.CoeffIdZero:
		return fr.Element{}
	case compiled.CoeffIdOne:
		return s.values[vID]
	case compiled.CoeffIdTwo:
		var res fr.Element
		res.Double(&s.values[vID])
		return res
	case compiled.CoeffIdMinusOne:
		var res fr.Element
		res.Neg(&s.values[vID])
		return res
	default:
		var res fr.Element
		res.Mul(&s.coefficients[cID], &s.values[vID])
		return res
	}
}