// Nearest returns the nearest grid point to p by rounding each dimensional // position to the nearest grid point. If the mesh basis is not the identity // matrix, then p is transformed to the mesh basis before rounding and then // retransformed back. func (m *InfMesh) Nearest(p []float64) []float64 { if m.StepSize == 0 { return append([]float64{}, p...) } else if l := len(m.Center); l != 0 && l != len(p) { panic(fmt.Sprintf("origin len %v incompatible with point len %v", l, len(p))) } // set up origin and inverter matrix if necessary if len(m.Center) == 0 { m.Center = make([]float64, len(p)) } if m.Basis != nil && m.inverter == nil { var err error m.inverter, err = mat64.Inverse(m.Basis) if err != nil { panic("basis inversion failed: " + err.Error()) } } // translate p based on origin and transform to new vector space newp := make([]float64, len(p)) for i := range newp { newp[i] = p[i] - m.Center[i] } v := mat64.NewDense(len(m.Center), 1, newp) rotv := v if m.inverter != nil { rotv.Mul(m.inverter, v) } // calculate nearest point nearest := mat64.NewDense(len(p), 1, nil) for i := range m.Center { n, rem := math.Modf(rotv.At(i, 0) / m.StepSize) if rem/m.StepSize > 0.5 { n++ } nearest.Set(i, 0, float64(n)*m.StepSize) } // transform back to standard space if m.Basis != nil { nearest.Mul(m.Basis, nearest) } nv := nearest.Col(nil, 0) for i := range nv { nv[i] += m.Center[i] } return nv }
// StackConstrBoxed converts the equations: // // lb <= Ix <= ub // and // low <= Ax <= up // // into a single equation of the form: // // Ax <= b func StackConstrBoxed(lb, ub []float64, low, A, up *mat64.Dense) (stackA, b *mat64.Dense, ranges []float64) { lbm := mat64.NewDense(len(lb), 1, lb) ubm := mat64.NewDense(len(ub), 1, ub) stacklow := &mat64.Dense{} stacklow.Stack(low, lbm) stackup := &mat64.Dense{} stackup.Stack(up, ubm) boxA := mat64.NewDense(len(lb), len(lb), nil) for i := 0; i < len(lb); i++ { boxA.Set(i, i, 1) } stacked := &mat64.Dense{} stacked.Stack(A, boxA) return StackConstr(stacklow, stacked, stackup) }
func (o *ObjectivePenalty) Objective(v []float64) (float64, error) { o.init() val, err := o.Obj.Objective(v) if o.Weight == 0 { return val, err } ax := &mat64.Dense{} x := mat64.NewDense(len(v), 1, v) ax.Mul(o.a, x) m, _ := ax.Dims() penalty := 0.0 for i := 0; i < m; i++ { if diff := ax.At(i, 0) - o.b.At(i, 0); diff > 0 { // maybe use "*=" for compounding penalty buildup penalty += diff / o.ranges[i] * o.Weight } } return val * (1 + penalty), err }
func (p *Point) Matrix() *mat64.Dense { return mat64.NewDense(p.Len(), 1, p.Pos) }
Step: 1.3, Basis: nil, Origin: []float64{0, 0}, Point: []float64{1.0, 1.0}, Exp: []float64{1.3, 1.3}, }, Problem{ Step: 1.3, Basis: nil, Origin: []float64{0, 0}, Point: []float64{1.9, 1.9}, Exp: []float64{1.3, 1.3}, }, Problem{ // 45 deg clockwise rotation of the identity basis Step: 1.0, Basis: mat64.NewDense(2, 2, []float64{1 / math.Sqrt(2), 1 / math.Sqrt(2), -1 / math.Sqrt(2), 1 / math.Sqrt(2)}), Origin: []float64{0, 0}, Point: []float64{1.0, 1.0}, Exp: []float64{1 / math.Sqrt(2), 1 / math.Sqrt(2)}, }, Problem{ // non-zero origin Step: 1.0, Basis: nil, Origin: []float64{0.2, 0.3}, Point: []float64{1.6, 2.1}, Exp: []float64{1.2, 2.3}, }, } func TestSimple(t *testing.T) { maxulps := uint64(1)