github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/physicscompress2/optimizer.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/gob"
     5  	"flag"
     6  	"fmt"
     7  	"math/rand"
     8  	"os"
     9  	"time"
    10  
    11  	"github.com/egonelbre/exp/bit"
    12  	"github.com/egonelbre/exp/coder/arith"
    13  	"github.com/egonelbre/exp/physicscompress2/physics"
    14  )
    15  
    16  func check(err error) {
    17  	if err != nil {
    18  		panic(err)
    19  	}
    20  }
    21  
    22  var (
    23  	tries = flag.Int("tries", 1e6, "how many random tries should it make")
    24  )
    25  
    26  func RandomModel() (m1, m2 arith.Model, desc string) {
    27  	switch rand.Intn(1) {
    28  	case 0:
    29  		x1 := arith.Shift2{
    30  			P0: arith.P(rand.Intn(arith.MaxP / 2)),
    31  			I0: byte(rand.Intn(8) + 1),
    32  			P1: arith.P(rand.Intn(arith.MaxP / 2)),
    33  			I1: byte(rand.Intn(8) + 1),
    34  		}
    35  		x2 := x1
    36  		m1, m2 = &x1, &x2
    37  	case 1:
    38  		x1 := arith.Shift4{
    39  			P: [4]arith.P{
    40  				arith.P(rand.Intn(arith.MaxP / 4)),
    41  				arith.P(rand.Intn(arith.MaxP / 4)),
    42  				arith.P(rand.Intn(arith.MaxP / 4)),
    43  				arith.P(rand.Intn(arith.MaxP / 4)),
    44  			},
    45  			I: [4]byte{
    46  				byte(rand.Intn(7) + 1),
    47  				byte(rand.Intn(7) + 1),
    48  				byte(rand.Intn(7) + 1),
    49  				byte(rand.Intn(7) + 1),
    50  			},
    51  		}
    52  		x2 := x1
    53  		m1, m2 = &x1, &x2
    54  	}
    55  	desc = fmt.Sprintf("%#v", m1)
    56  	return
    57  }
    58  
    59  func RandomTree(nbits uint) (m1 arith.Model, desc string) {
    60  	x1 := arith.Shift2{
    61  		P0: arith.P(rand.Intn(arith.MaxP / 2)),
    62  		I0: byte(rand.Intn(8) + 1),
    63  		P1: arith.P(rand.Intn(arith.MaxP / 2)),
    64  		I1: byte(rand.Intn(8) + 1),
    65  	}
    66  
    67  	m1 = arith.NewTree(nbits, func() arith.Model {
    68  		x := x1
    69  		return &x
    70  	})
    71  
    72  	desc = fmt.Sprintf("%#v", x1)
    73  	return
    74  }
    75  
    76  func main() {
    77  	flag.Parse()
    78  
    79  	rand.Seed(time.Now().UnixNano())
    80  
    81  	var baseline []physics.Cube
    82  	var current []physics.Cube
    83  
    84  	file, err := os.Open(flag.Arg(0))
    85  	check(err)
    86  
    87  	dec := gob.NewDecoder(file)
    88  	dec.Decode(&current)
    89  	dec.Decode(&baseline)
    90  
    91  	minimal := 1 << 10
    92  
    93  	items := []int{}
    94  	for i := range current {
    95  		cube, base := &current[i], &baseline[i]
    96  		if *cube != *base {
    97  			items = append(items, i)
    98  		}
    99  	}
   100  
   101  	items6 := physics.Index6(items, len(current))
   102  	cur6 := physics.Delta6(baseline, current)
   103  	max := uint64(0)
   104  	for _, i := range items6 {
   105  		ext := uint64(bit.ZEncode(int64(cur6(i))))
   106  		if max < ext {
   107  			max = ext
   108  		}
   109  	}
   110  
   111  	nbits := bit.ScanRight(max) + 1
   112  
   113  	for i := 0; i < *tries; i += 1 {
   114  		menc, desc := RandomTree(nbits)
   115  		enc := arith.NewEncoder()
   116  
   117  		for _, i := range items {
   118  			cube := &current[i]
   119  			menc.Encode(enc, uint(cube.Interacting^1))
   120  		}
   121  
   122  		for _, i := range items {
   123  			cube, base := &current[i], &baseline[i]
   124  			v := uint(cube.Largest ^ base.Largest)
   125  			menc.Encode(enc, v&1)
   126  			menc.Encode(enc, v>>1)
   127  		}
   128  
   129  		enc.Close()
   130  
   131  		if len(enc.Bytes()) < minimal {
   132  			fmt.Printf("%6d %5d   - %s\n", i, len(enc.Bytes()), desc)
   133  			minimal = len(enc.Bytes())
   134  		}
   135  	}
   136  }